21年10月第四周 力扣每日一题记录

本周每日一题 题目

  • lc476. 数字的补数
  • lc211. 添加与搜索单词 - 数据结构设计
  • lc453. 最小操作次数使数组元素相等
  • lc66. 加一
  • lc229. 求众数 II
  • lc492. 构造矩形

10-18 lc476. 数字的补数

  • 对示例做这样一个事,求num+答案+1,结果刚好是2^n,然后再用几个测试用例,发现也是这样,所以这就是本题的规律
  • 然后这个2^n是大于num的最小的n,所以答案如下
  • 用long来解决边界溢出
class Solution {
    
    
    public int findComplement(int num) {
    
    
        long n = 1;
        while(n<=num) n = n << 1;
        return (int)(n-num-1);
    }
}

10-19 lc211. 添加与搜索单词 - 数据结构设计

  • 就是一个字典树,然后加上万能匹符的逻辑
  • 好久没有写字典树了,好生疏,写了好久
  • 然后这里万能符匹配,要麻烦一点,需要递归调用,跳过当前字符,从next节点来匹配后序字符,看是否能够成功
class WordDictionary {
    
    
    //只需要来查询是否存在,而且单词的长度也有限,所以完全可以建立一个500*26的数组来记录每个位置的单词情况
    //还有就是是否要以当前字母结尾,所以就是一个字典树,得专门记录一个end的状态,才能统计
    //就是字典树,但难度还是有的,因为是有一个万能匹配符
    class WordTree{
    
    
        boolean end = false;
        WordTree[] next = new WordTree[26];//下一个数组,26个字母,未初始化
    }
    private WordTree root;

    /** Initialize your data structure here. */
    public WordDictionary() {
    
    
        root = new WordTree();
    }
    
    /** Adds a word into the data structure. */
    public void addWord(String word) {
    
    
        char[] ss = word.toCharArray();
        WordTree cur = this.root;
        for(char ch : ss){
    
    
            int i = ch-97;
            if(cur.next[i]==null)
                cur.next[i] = new WordTree();
            cur = cur.next[i];
        }
        cur.end = true;//end设置为true
    }
    
    /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
    public boolean search(String word) {
    
    
        return help(root,word);
    }

    private boolean help(WordTree cur, String word){
    
    
        if(cur==null) return false;
        char[] ss = word.toCharArray();
        for(int j=0; j<ss.length; j++){
    
    
            char ch = ss[j];
            if(ch=='.'){
    
    //当出现万能匹配符时,最多可能有26种可能,都要去尝试
                for(int i=0; i<26; i++)
                    if(help(cur.next[i],String.valueOf(ss,j+1,ss.length-j-1))) return true;
                return false;
            }
            int i = ch-97;
            if(cur.next[i]==null) return false;
            cur = cur.next[i];
        }
        return cur.end;
    }
}

10-20 lc453. 最小操作次数使数组元素相等

  • 这是一个数学题
 设变量t为最终平衡的数值,而x为我们最小操作数
 数值长度为n,和为sum
 可以得到  n*t = x*(n-1) + sum (1)
 然后对于我们数组中的最小值min,它有这样的等式关系 t - min = x (2)
 对于上面的等式,它是必须成立的,设想如果不等于,那么等式要么大于要么小于;大于的话,明显不平衡,小于的话,说明达不到平衡
 联立(1)(2)
 解得 x = sum - min * n;
class Solution {
    
    
   //n-1个元素增加1
   //如果每次都不给本轮最大值加,是不是就可以到最终结果了,一个贪心的思路,就总能够达到平衡
   //那么要求多少轮的话,每一轮都能知道,至少有多少个要加,这个复杂度高,不可能模拟的
   public int minMoves(int[] nums) {
    
    
       int sum = 0;
       int min = (int)1e9;
       for(int num: nums){
    
    
           if(num<min) min = num;
           sum += num;
       }
       return sum-min*nums.length;
   }
}

10-21 lc66. 加一

  • 就是一个大数加法
  • 唯一麻烦一点的是,返回数组,所以不知道返回数组的长度==原数组长度还是+1
  • 所以用list先存着,之后转数组,可我总是。。记不得java的List转int[],list.stream().mapToInt(i->i).toArray();
class Solution {
    
    
    //非负,整个数组就是一个数
    //所以这个就是一个加1的操作,大数加法,然后因为是数组,所以要考虑进位之后比之前多一位的情况,所以需要准备新数组
    //于是用List来存储,最终reverse,转换成数组
    public int[] plusOne(int[] digits) {
    
    
        List<Integer> list = new ArrayList<>();
        int t = 1;
        for(int i=digits.length-1; i>=0; i--){
    
    
            int d = digits[i];
            list.add((d+t)%10);
            t = (d + t)/10;
        }
        if(t!=0) list.add(t);
        Collections.reverse(list);//因为从低位开始,所以是反着的
        return list.stream().mapToInt(i->i).toArray();
    }
}

10-22 lc229. 求众数 II

  • 升级版的摩尔技术法,这里是求超过n/3的,和n/2不同
  • 本题是超过n/3,如果是大于等于n/3的,其实就不好求了,可能说要通过3个变量来求了,嗯,3个是可以的
  • 所以求>n/k的,用k-1个变量,注意continue(一轮只命中一个),求>=n/k的,用k个变量,注意continue,注意continue
class Solution {
    
    
    public List<Integer> majorityElement(int[] nums) {
    
    
        List<Integer> res = new ArrayList<>();
        if(nums==null || nums.length==0)return res;
        //升级版摩尔计数法
        //同时只有一个人进行++操作
        int cand1 = nums[0], cnt1 = 0;
        int cand2 = nums[0], cnt2 = 0;
        //找出两个众数
        for(int num : nums){
    
    
            if(cand1==num){
    
    
                cnt1++;
                continue;
            }
            if(cand2==num){
    
    
                cnt2++;
                continue;
            }
            if(cnt1==0){
    
    
                cand1 = num;
                cnt1++;
                continue;
            }
            if(cnt2==0){
    
    
                cand2 = num;
                cnt2++;
                continue;
            }
            cnt1--;
            cnt2--;
        }
        //这里count1和count2,有被抵消了,可能刚好为0,所以不行,要重新统计
        cnt1 = 0;
        cnt2 = 0;
        for(int num: nums)
            if(num==cand1) cnt1++;
            else if(num==cand2) cnt2++;


        if(cnt1>(int)nums.length/3)res.add(cand1);
        if(cnt2>(int)nums.length/3)res.add(cand2);
        return res;
    }
}

10-23 lc492. 构造矩形

  • 就是给定面积,求最接近正方形的矩形的长宽
  • 思路很简单,从平方数开始,往下减少,直到面积除以当前宽能够余数为0,就终止
class Solution {
    
    
    //尽量是正方形呗
    //先长后宽
    public int[] constructRectangle(int area) {
    
    
        int w = (int)Math.sqrt(area);
        while(area%w!=0) w--;
        return new int[]{
    
    area/w,w};
    }
}

猜你喜欢

转载自blog.csdn.net/qq_34687559/article/details/120820198