5930. 两栋颜色不同且距离最远的房子

街上有 n 栋房子整齐地排成一列,每栋房子都粉刷上了漂亮的颜色。给你一个下标从 0 开始且长度为 n 的整数数组 colors ,其中 colors[i] 表示第 i 栋房子的颜色。
返回 两栋 颜色 不同 房子之间的 最大 距离。
i 栋房子和第 j 栋房子之间的距离是 abs(i - j) ,其中 abs(x)x 的绝对值。

示例 1:
🏆 第 268 场力扣周赛 - 图1
输入:colors = [1,1,1,6,1,1,1]
输出:3
解释:上图中,颜色 1 标识成蓝色,颜色 6 标识成红色。
两栋颜色不同且距离最远的房子是房子 0 和房子 3 。
房子 0 的颜色是颜色 1 ,房子 3 的颜色是颜色 6 。两栋房子之间的距离是 abs(0 - 3) = 3 。
注意,房子 3 和房子 6 也可以产生最佳答案。

示例 2:
🏆 第 268 场力扣周赛 - 图2
输入:colors = [1,8,3,8,3]
输出:4
解释:上图中,颜色 1 标识成蓝色,颜色 8 标识成黄色,颜色 3 标识成绿色。
两栋颜色不同且距离最远的房子是房子 0 和房子 4 。
房子 0 的颜色是颜色 1 ,房子 4 的颜色是颜色 3 。两栋房子之间的距离是 abs(0 - 4) = 4 。

示例 3:
输入:colors = [0,1]
输出:1
解释:两栋颜色不同且距离最远的房子是房子 0 和房子 1 。
房子 0 的颜色是颜色 0 ,房子 1 的颜色是颜色 1 。两栋房子之间的距离是 abs(0 - 1) = 1 。


提示:

  • n == colors.length
  • 2 <= n <= 100
  • 0 <= colors[i] <= 100
  • 生成的测试数据满足 至少 存在 2 栋颜色不同的房子

思路:
题目已经保证了一定存在结果,数据范围只有100,直接爆搜,时间复杂度为O(n^2)

  1. class Solution {
  2. public int maxDistance(int[] colors) {
  3. int res = 0;
  4. for (int i = 0; i < colors.length; i++) {
  5. for (int j = colors.length - 1; j > i; j--) {
  6. if (colors[i] != colors[j]) {
  7. res = Math.max(j - i, res);
  8. }
  9. }
  10. }
  11. return res;
  12. }
  13. }

5201. 给植物浇水

你打算用一个水罐给花园里的 n 株植物浇水。植物排成一行,从左到右进行标记,编号从 0n - 1 。其中,第 i 株植物的位置是 x = ix = -1 处有一条河,你可以在那里重新灌满你的水罐。
每一株植物都需要浇特定量的水。你将会按下面描述的方式完成浇水:

  • 按从左到右的顺序给植物浇水。
  • 在给当前植物浇完水之后,如果你没有足够的水 完全 浇灌下一株植物,那么你就需要返回河边重新装满水罐。
  • 不能 提前重新灌满水罐。

最初,你在河边(也就是,x = -1),在 x 轴上每移动 一个单位 都需要 一步
给你一个下标从 0 开始的整数数组 plants ,数组由 n 个整数组成。其中,plants[i] 为第 i 株植物需要的水量。另有一个整数 capacity 表示水罐的容量,返回浇灌所有植物需要的 步数

示例 1:
输入:plants = [2,2,3,3], capacity = 5
输出:14
解释:从河边开始,此时水罐是装满的:
- 走到植物 0 (1 步) ,浇水。水罐中还有 3 单位的水。
- 走到植物 1 (1 步) ,浇水。水罐中还有 1 单位的水。
- 由于不能完全浇灌植物 2 ,回到河边取水 (2 步)。
- 走到植物 2 (3 步) ,浇水。水罐中还有 2 单位的水。
- 由于不能完全浇灌植物 3 ,回到河边取水 (3 步)。
- 走到植物 3 (4 步) ,浇水。
需要的步数是 = 1 + 1 + 2 + 3 + 3 + 4 = 14 。

示例 2:
输入:plants = [1,1,1,4,2,3], capacity = 4
输出:30
解释:从河边开始,此时水罐是装满的:
- 走到植物 0,1,2 (3 步) ,浇水。回到河边取水 (3 步)。
- 走到植物 3 (4 步) ,浇水。回到河边取水 (4 步)。
- 走到植物 4 (5 步) ,浇水。回到河边取水 (5 步)。
- 走到植物 5 (6 步) ,浇水。
需要的步数是 = 3 + 3 + 4 + 4 + 5 + 5 + 6 = 30 。
示例 3:
输入:plants = [7,7,7,7,7,7,7], capacity = 8
输出:49
解释:每次浇水都需要重新灌满水罐。
需要的步数是 = 1 + 1 + 2 + 2 + 3 + 3 + 4 + 4 + 5 + 5 + 6 + 6 + 7 = 49 。


提示:

  • n == plants.length
  • 1 <= n <= 1000
  • 1 <= plants[i] <= 10
  • max(plants[i]) <= capacity <= 10

思路:
一道模拟题
直接从前往后扫描一遍即可!时间复杂度为O(n)

  1. class Solution {
  2. public int wateringPlants(int[] plants, int capacity) {
  3. int res = 0, sum = capacity;
  4. for (int i = 0; i < plants.length; i++) {
  5. if (sum >= plants[i]) {
  6. res++;
  7. sum -= plants[i];
  8. } else {
  9. res += i + i + 1;
  10. sum = capacity - plants[i];
  11. }
  12. }
  13. return res;
  14. }
  15. }

5186. 区间内查询数字的频率

难度中等11收藏分享切换为英文接收动态反馈
请你设计一个数据结构,它能求出给定子数组内一个给定值的 频率
子数组中一个值的 频率 指的是这个子数组中这个值的出现次数。
请你实现 RangeFreqQuery 类:

  • RangeFreqQuery(int[] arr) 用下标从 0 开始的整数数组 arr 构造一个类的实例。
  • int query(int left, int right, int value) 返回子数组 arr[left...right]value频率

一个 子数组 指的是数组中一段连续的元素。arr[left...right] 指的是 nums 中包含下标 leftright 在内 的中间一段连续元素。

示例 1:
输入:
[“RangeFreqQuery”, “query”, “query”]
[[[12, 33, 4, 56, 22, 2, 34, 33, 22, 12, 34, 56]], [1, 2, 4], [0, 11, 33]]
输出:
[null, 1, 2]

解释:
RangeFreqQuery rangeFreqQuery = new RangeFreqQuery([12, 33, 4, 56, 22, 2, 34, 33, 22, 12, 34, 56]);
rangeFreqQuery.query(1, 2, 4); // 返回 1 。4 在子数组 [33, 4] 中出现 1 次。
rangeFreqQuery.query(0, 11, 33); // 返回 2 。33 在整个子数组中出现 2 次。


提示:

  • 1 <= arr.length <= 10
  • 1 <= arr[i], value <= 10
  • 0 <= left <= right < arr.length
  • 调用 query 不超过 10 次。

思路:
用哈希表存储每个数字在数组中出现的所有下标 Map<Integer, List<Integer>>
二分查找给定区间目标数字出现的次数!

  1. class RangeFreqQuery {
  2. Map<Integer, List<Integer>> map = new HashMap<>();
  3. public RangeFreqQuery(int[] arr) {
  4. for (int i = 0; i < arr.length; i++) {
  5. if (!map.containsKey(arr[i])) {
  6. List<Integer> list = new ArrayList<>();
  7. list.add(i);
  8. map.put(arr[i], list);
  9. } else
  10. map.get(arr[i]).add(i);
  11. }
  12. }
  13. public int query(int left, int right, int value) {
  14. List<Integer> list = map.get(value);
  15. if (list == null) return 0;
  16. //当然这里也可以手写二分,比赛时我就是手写的,,
  17. int l = Collections.binarySearch(list, left);
  18. if (l < 0) l = -(l + 1);
  19. if (l >= list.size() || list.get(l) > right)
  20. return 0;
  21. int r = Collections.binarySearch(list, right);
  22. if (r < 0) {
  23. r = -(r + 1);
  24. return r - l;
  25. } else {
  26. return r - l + 1;
  27. }
  28. }
  29. }
  30. /**
  31. * Your RangeFreqQuery object will be instantiated and called as such:
  32. * RangeFreqQuery obj = new RangeFreqQuery(arr);
  33. * int param_1 = obj.query(left,right,value);
  34. */

💡5933. k 镜像数字的和

一个 k 镜像数字 指的是一个在十进制和 k 进制下从前往后读和从后往前读都一样的 没有前导 0 整数。

  • 比方说,9 是一个 2 镜像数字。9 在十进制下为 9 ,二进制下为 1001 ,两者从前往后读和从后往前读都一样。
  • 相反地,4 不是一个 2 镜像数字。4 在二进制下为 100 ,从前往后和从后往前读不相同。

给你进制 k 和一个数字 n ,请你返回 k 镜像数字中 最小n 个数 之和

示例 1:
输入:k = 2, n = 5
输出:25
解释:
最小的 5 个 2 镜像数字和它们的二进制表示如下:
十进制 二进制
1 1
3 11
5 101
7 111
9 1001
它们的和为 1 + 3 + 5 + 7 + 9 = 25 。

示例 2:
输入:k = 3, n = 7
输出:499
解释:
7 个最小的 3 镜像数字和它们的三进制表示如下:
十进制 三进制
1 1
2 2
4 11
8 22
121 11111
151 12121
212 21212
它们的和为 1 + 2 + 4 + 8 + 121 + 151 + 212 = 499 。

示例 3:
输入:k = 7, n = 17
输出:20379000
解释:17 个最小的 7 镜像数字分别为:
1, 2, 3, 4, 5, 6, 8, 121, 171, 242, 292, 16561, 65656, 2137312, 4602064, 6597956, 6958596


提示:

  • 2 <= k <= 9
  • 1 <= n <= 30

思路:
比赛的时候没想到解法,暴力打表
实际上是一道构造题,从小往大构造每个回文十进制数,将其转换成k进制数判断其是否仍是回文数,直至找到n个数为止,返回这n个数的和
注意:构造回文数时,每个数要考虑奇偶长度,例如,给定数 1234 用它构造回文数可以是 1234321 或者 12344321
还要保证构造的回文数是按照从小到大的顺序来的!

  1. class Solution {
  2. public long kMirror(int k, int n) {
  3. long res = 0;
  4. for (int len = 1; ; len++) {
  5. //这两行太妙了,每组长度的数字都取了两次!!!
  6. long x = (long)Math.pow(10, (len - 1) / 2);
  7. long y = (long)Math.pow(10, (len + 1) / 2);
  8. for (long i = x; i < y; i++) {
  9. long b = i;
  10. //根据len奇偶性构造奇偶长度的回文串
  11. for (long j = len % 2 == 1 ? i / 10 : i; j > 0; j /= 10) {
  12. b = b * 10 + j % 10;
  13. }
  14. //这个函数可以直接将一个数转换为对应进制字符串
  15. String s = Long.toString(b, k);
  16. if (check(s.toCharArray())) {
  17. res += b;
  18. if (--n == 0)
  19. return res;
  20. }
  21. }
  22. }
  23. }
  24. boolean check(char[] chars) {
  25. for (int i = 0, j = chars.length - 1; i < j; i++, j--)
  26. if (chars[i] != chars[j])
  27. return false;
  28. return true;
  29. }
  30. }