LeetCode 744. 寻找比目标字母大的最小字母 / 307. 区域和检索 - 数组可修改 / 762. 二进制表示中质数个计算置位

Posted Zephyr丶J

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 744. 寻找比目标字母大的最小字母 / 307. 区域和检索 - 数组可修改 / 762. 二进制表示中质数个计算置位相关的知识,希望对你有一定的参考价值。

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)
链接:https://leetcode-cn.com/problems/find-smallest-letter-greater-than-target
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

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 ,请你完成两类查询。

  1. 其中一类查询要求 更新 数组 nums 下标对应的值
  2. 另一类查询要求返回数组 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)
链接:https://leetcode-cn.com/problems/range-sum-query-mutable
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

之前做过,也知道是树状数组,好久没写了,这里复习一下

首先掌握第一点,就是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)
链接:https://leetcode-cn.com/problems/prime-number-of-set-bits-in-binary-representation
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

两个点,一个是怎么统计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))

以上是关于LeetCode 744. 寻找比目标字母大的最小字母 / 307. 区域和检索 - 数组可修改 / 762. 二进制表示中质数个计算置位的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 744. 寻找比目标字母大的最小字母 / 307. 区域和检索 - 数组可修改 / 762. 二进制表示中质数个计算置位

⭐算法入门⭐《二分枚举》简单05 —— LeetCode 744. 寻找比目标字母大的最小字母

leetcode 744. 寻找比目标字母大的最小字母(Find Smallest Letter Greater Than Target)

LeetCode 744 寻找比目标字母大的最小字母[二分法] HERODING的LeetCode之路

LeetCode 744 寻找比目标字母大的最小字母[二分法] HERODING的LeetCode之路

744. 寻找比目标字母大的最小字母