每日刷题记录 (三十)

x33g5p2x  于2022-07-22 转载在 其他  
字(3.7k)|赞(0)|评价(0)|浏览(161)

第一题: 396. 旋转函数

LeetCode: 396. 旋转函数

描述:

给定一个长度为 n 的整数数组 nums 。

假设 arrk 是数组 nums 顺时针旋转 k 个位置后的数组,我们定义 nums 的 旋转函数 F 为:

  • F(k) = 0 * arrk[0] + 1 * arrk[1] + ... + (n - 1) * arrk[n - 1]

返回 F(0), F(1), ..., F(n-1) 中的最大值 。

生成的测试用例让答案符合 32 位 整数。

解题思路:

  1. F(0) = 0*A[0]+1*A[1]+2*A[2]+3*A[3]
    F(1) = 0*A[3]+1*A[0]+2*A[1]+3*A[2]
    F(2) = 0*A[2]+1*A[3]+2*A[0]+3*A[1]
    F(3) = 0*A[1]+1*A[2]+2*A[3]+3*A[0]
  2. F(1)-F(0) = A[0]+A[1]+A[2]-3*A[3]
    F(2)-F(1) = A[0]+A[1]+A[3]-3*A[2]
    F(3)-F(2) = A[0]+A[2]+A[3]-3*A[1]
  3. sum = A[0]+A[1]+A[2]+A[3]
  4. F(3) - F(2) = sum - 4 * A[1]
    F(2) - F(1) = sum - 4 * A[2]
    F(1) - F(0) = sum - 4 * A[3]
  5. F(n) - F(n-1) = sum - len * A(len - n)

代码实现:

class Solution {
    public int maxRotateFunction(int[] nums) {
        int sum = 0;
        int max = 0;
        for(int i = 0; i < nums.length; i++) {
            sum += nums[i];// 求 Sum
            max += i * nums[i]; // 求F(0)
        }
        int tmp = max;
        for(int i = 1; i < nums.length; i++) {
            tmp += sum - nums.length * nums[nums.length - i]; // F(n) - F(n-1) =  sum - len * A(len - n)
            max = Math.max(tmp,max);
        }
        return max;
    }
}

第二题: 397. 整数替换

LeetCode: 397. 整数替换

描述:
给定一个正整数 n ,你可以做如下操作:

  1. 如果 n 是偶数,则用 n / 2替换 n 。
  2. 如果 n 是奇数,则可以用 n + 1或n - 1替换 n 。

返回 n 变为 1 所需的 最小替换次数 。

解题思路:

  1. 如果是偶数, 那么就直接 /2
  • 如果是奇数

  • 首先判断是否为连续的1, 连续1, 就 +1

  • 单个1, 就-1

  • 特殊的3的情况, 直接返回次数+2;

代码实现:

class Solution {
    public int integerReplacement(int n) {
        long num = n;
        int res = 0;
        while(num > 1) {
            if(num == 3) return res + 2;
            if(num % 2 == 0){
                num/=2;
            }else{
                if((num & 3) == 1) num--;
                else num++;
            }
            res++;
        }
        return res;
    }
}

第三题: 398. 随机数索引

LeetCode: 398. 随机数索引

描述:
给你一个可能含有 重复元素 的整数数组 nums ,请你随机输出给定的目标数字 target 的索引。你可以假设给定的数字一定存在于数组中。

实现 Solution 类:

  • Solution(int[] nums) 用数组 nums 初始化对象。
  • int pick(int target) 从 nums 中选出一个满足 nums[i] == target 的随机索引 i 。如果存在多个有效的索引,则每个索引的返回概率应当相等。

解题思路:

  1. 这里使用哈希表解题的思路.
  2. key记录当前的数值, value使用List记录所有值为value的下标
  3. pick方法的时候, 获取到存放下标的 List , 然后使用random函数, 随机获取下标, 然后返回.

代码实现:

class Solution {

    Random random;
    Map<Integer,List<Integer>> map = new HashMap();
    public Solution(int[] nums) {
        random = new Random();
        for(int i = 0; i < nums.length; i++) {
            if(map.containsKey(nums[i])){
                map.get(nums[i]).add(i);
            }else{
                List<Integer> list = new ArrayList<>();
                list.add(i);
                map.put(nums[i],list);
            }
        }
    }
    
    public int pick(int target) {
        List<Integer> list = map.get(target);
        return list.get(random.nextInt(list.size()));
    }
}

第四题: 451. 根据字符出现频率排序

LeetCode: 451. 根据字符出现频率排序

描述:
给定一个字符串 s ,根据字符出现的 频率 对其进行 降序排序 。一个字符出现的 频率 是它出现在字符串中的次数。

返回 已排序的字符串 。如果有多个答案,返回其中任何一个

解题思路:

  1. 这里首先使用一个数组, 来对字符串中字符出现的次数进行计算.
  2. 在使用一个优先级队列, 堆顶存放次数较多的字符.
  3. 最后进行拼接. 每次弹出堆顶元素.
  4. 拼接好之后进行返回.

代码实现:

class Solution {
    public String frequencySort(String s) {
        int[] count = new int[128];
        PriorityQueue<Integer> pq = new PriorityQueue<>((o1,o2)->count[o2] - count[o1]);
        for(char ch : s.toCharArray()) count[ch]++;
        for(int i = 0; i < 128; i++) {
            if(count[i] > 0) {
                pq.add(i);
            }
        }
        StringBuilder res = new StringBuilder();
        while(!pq.isEmpty()) {
            int top = pq.poll();
            for(int i = 0; i < count[top]; i++) {
                res.append((char)top);
            }
        }
        return res.toString();
    }
}

第五题: 454. 四数相加 II

LeetCode: 454. 四数相加 II

描述:
给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

  • 0 <= i, j, k, l < n
  • nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

解题思路:

  1. 这里使用两两遍历的方式.
  2. 首先对 nums1 , nums2 进行遍历, 每次将遍历到的元素求和, 然后放入哈希表中. key 为对应的和, value为对应和出现的次数
  3. 再去遍历 nums3nums4, 每次将遍历到的和加上负号, 在哈希表中去找, 如果存在, 表示可以和为0, 那么就得到对应的value值, 然后加到结果中.

代码实现:

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        Map<Integer,Integer> map = new HashMap<>();
        int ret = 0;
        int res = 0;
        for (int val1 : nums1){
            for (int val2 : nums2) {
                ret = val1 + val2;
                if(map.containsKey(ret)) {
                    map.put(ret,map.get(ret) + 1);
                }else{
                    map.put(ret,1);
                }
            }
        }
        for (int val1 : nums3){
            for (int val2 : nums4) {
                ret = val1 + val2;
                if (map.containsKey(0 - ret)) {
                    res += map.get(0 - ret);
                }
            }
        }
        return res;
    }
}

第六题: 476. 数字的补数

LeetCode: 476. 数字的补数

描述:
对整数的二进制表示取反(0 变 1 ,1 变 0)后,再转换为十进制表示,可以得到这个整数的补数。

  • 例如,整数 5 的二进制表示是 “101” ,取反后得到 “010” ,再转回十进制表示得到补数 2 。

给你一个整数 num ,输出它的补数。

解题思路:

  1. 这里使用位运算.
  2. 首先去记录这个数字一共占了多少为. 循环去判断这个数是否等于0, 不等于的时候去右移1个.
  3. 每次移动的时候, 再去用一个数字, 在每位都置为1
  4. 例如, 5, 二进制为 101, 占了3个位置. 然后就用另一个数字每位为1, 111, 用这个数字去和 5 进行异或操作.
  5. 异或之后, 就是补数.

代码实现:

class Solution {
    public int findComplement(int num) {
        int tmp = num;
        int ret = 0;
        while(tmp > 0) {
            tmp >>= 1;
            ret = (ret << 1) | 1;
        }
        return ret ^ num;
    }
}

相关文章