本文已参与「新人创作礼」活动,一起开启掘金创作之路。
744. 寻找比目标字母大的最小字母
2022.4.3 每日一题
题目描述
给你一个排序后的字符列表 letters ,列表中只包含小写英文字母。另给出一个目标字母 target,请你寻找在这一有序列表里比目标字母大的最小字母。
在比较时,字母是依序循环出现的。举个例子:
如果目标字母 target = 'z' 并且字符列表为 letters = ['a', 'b'],则答案返回 'a'
示例 1:
输入: letters = ["c", "f", "j"],target = "a" 输出: "c"
示例 2:
输入: letters = ["c","f","j"], target = "c" 输出: "f"
示例 3:
输入: letters = ["c","f","j"], target = "d" 输出: "f"
提示:
2 <= letters.length <= 10^4 letters[i] 是一个小写字母 letters 按非递减顺序排序 letters 最少包含两个不同的字母 target 是一个小写字母
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/fi… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
class Solution {
public char nextGreatestLetter(char[] letters, char target) {
//二分
int l = letters.length;
int left = 0;
int right = l - 1;
while(left < right){
int mid = (right - left) / 2 + left;
if(letters[mid] <= target){
left = mid + 1;
}else{
right = mid;
}
}
//如果找到头了,还没有找到比target大的
return letters[left] <= target ? letters[0] : letters[left];
}
}
class Solution:
def nextGreatestLetter(self, letters: List[str], target: str) -> str:
left, right = 0, len(letters) - 1
while left < right:
mid = (int)((right - left) / 2 + left)
if letters[mid] <= target:
left = mid + 1
else:
right = mid
return letters[left] if letters[left] > target else letters[0]
class Solution:
def nextGreatestLetter(self, letters: List[str], target: str) -> str:
return letters[r] if (r := bisect_right(letters, target)) < len(letters) else letters[0]
307. 区域和检索 - 数组可修改
2022.4.4 每日一题
题目描述
给你一个数组 nums ,请你完成两类查询。
- 其中一类查询要求 更新 数组 nums 下标对应的值
- 另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 ,其中 left <= right
实现 NumArray 类:
- NumArray(int[] nums) 用整数数组 nums 初始化对象
- void update(int index, int val) 将 nums[index] 的值 更新 为 val
- int sumRange(int left, int right) 返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 (即,nums[left] + nums[left + 1], ..., nums[right])
示例 1:
输入: ["NumArray", "sumRange", "update", "sumRange"] [[[1, 3, 5]], [0, 2], [1, 2], [0, 2]] 输出: [null, 9, null, 8] 解释: NumArray numArray = new NumArray([1, 3, 5]); numArray.sumRange(0, 2); // 返回 1 + 3 + 5 = 9 numArray.update(1, 2); // nums = [1,2,5] numArray.sumRange(0, 2); // 返回 1 + 2 + 5 = 8
提示:
1 <= nums.length <= 3 * 10^4 -100 <= nums[i] <= 100 0 <= index < nums.length -100 <= val <= 100 0 <= left <= right < nums.length 调用 update 和 sumRange 方法次数不大于 3 * 10^4
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/ra… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
之前做过,也知道是树状数组,好久没写了,这里复习一下
首先掌握第一点,就是lowbit,取的是一个数二进制位中最小位置的1 然后第二点,明白树状数组的结构,这是理解树状数组的前提 树状数组中的数代表的是一个特定区间的和,而不是一个单独的数,所以说用树状数组计算会降低时间复杂度 两个操作,更新和查询都依赖lowbit,更新需要自底向上更新,查询需要从上至下查询
长度要比nums数组大1是因为,如果下标为0的话会进入死循环
class NumArray {
int[] tree;
public int lowbit(int x){
return x & (-x);
}
public void add(int x, int u){
for(int i = x; i <= n; i += lowbit(i))
tree[i] += u;
}
public int query(int x){
int res = 0;
for(int i = x; i > 0; i -= lowbit(i))
res += tree[i];
return res;
}
int[] nums;
int n;
public NumArray(int[] nums) {
this.nums = nums;
n = nums.length;
tree = new int[n + 1];
for(int i = 0; i < n; i++){
add(i + 1, nums[i]);
}
}
public void update(int index, int val) {
int diff = val - nums[index];
add(index + 1, diff);
nums[index] = val;
}
public int sumRange(int left, int right) {
return query(right + 1) - query(left);
}
}
/**
* Your NumArray object will be instantiated and called as such:
* NumArray obj = new NumArray(nums);
* obj.update(index,val);
* int param_2 = obj.sumRange(left,right);
*/
class NumArray:
def __init__(self, nums: List[int]):
self.nums = nums
self.tree = [0] * (len(nums) + 1)
for i, num in enumerate(nums, 1):
self.add(i, num)
def lowbit(self, x : int) -> int:
return x & -x
def add(self, index : int, val : int):
while index <= len(self.nums):
self.tree[index] += val
index += self.lowbit(index)
def query(self, index : int) -> int:
ans = 0
while index:
ans += self.tree[index]
index -= self.lowbit(index)
return ans
def update(self, index: int, val: int) -> None:
self.add(index + 1, val - self.nums[index])
self.nums[index] = val
def sumRange(self, left: int, right: int) -> int:
return self.query(right + 1) - self.query(left)
# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# obj.update(index,val)
# param_2 = obj.sumRange(left,right)
762. 二进制表示中质数个计算置位
2022.4.5 每日一题
题目描述
给你两个整数 left 和 right ,在闭区间 [left, right] 范围内,统计并返回 计算置位位数为质数 的整数个数。
计算置位位数 就是二进制表示中 1 的个数。
- 例如, 21 的二进制表示 10101 有 3 个计算置位。
示例 1:
输入:left = 6, right = 10 输出:4 解释: 6 -> 110 (2 个计算置位,2 是质数) 7 -> 111 (3 个计算置位,3 是质数) 9 -> 1001 (2 个计算置位,2 是质数) 10-> 1010 (2 个计算置位,2 是质数) 共计 4 个计算置位为质数的数字。
示例 2:
输入:left = 10, right = 15 输出:5 解释: 10 -> 1010 (2 个计算置位, 2 是质数) 11 -> 1011 (3 个计算置位, 3 是质数) 12 -> 1100 (2 个计算置位, 2 是质数) 13 -> 1101 (3 个计算置位, 3 是质数) 14 -> 1110 (3 个计算置位, 3 是质数) 15 -> 1111 (4 个计算置位, 4 不是质数) 共计 5 个计算置位为质数的数字。
提示:
1 <= left <= right <= 10^6 0 <= right - left <= 10^4
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/pr… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
两个点,一个是怎么统计1的个数,一个是怎么判断是不是质数 但是因为这里质数最大32,所以直接列出来就行了 统计1的个数用的bitCount
class Solution {
static int[] primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
static Set<Integer> set;
static{
set = new HashSet<>();
for(int t : primes){
set.add(t);
}
}
public int countPrimeSetBits(int left, int right) {
int count = 0;
for(int i = left; i <= right; i++){
if(set.contains(Integer.bitCount(i)))
count++;
}
return count;
}
}
这个数组竟然要在class外面定义,需要好好研究一下python的语法了
PRIMES = {2,3,5,7,11,13,17,19}
class Solution:
def countPrimeSetBits(self, left: int, right: int) -> int:
return sum(i.bit_count() in PRIMES for i in range(left, right + 1))