力扣刷题总结


自己做过的力扣题总结

1.位运算

260. 只出现一次的数字 III

给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案

思路: x&(-x)

取到的结果就是把自身x最低位1和后面的0保存,其余位都是0
e.g:
lowbit(6):6的二进制是(110)所以结果就是(10)
lowbit(7):7的二进制是(111)所以结果就是(1)
然后把结果转化10进制就可以了
快速办法直接看 最低位1取到的是第几位,然后2的几次方就可以了
比如lowbit(6) 最低位1 在第1位上 所以2^1=2;
lowbit (7) 最低位1 在第0位上 所以2^0=1

用途: 一般可以用来获取某个二进制数的LowBit

然后分别与各个数做&运算,&结果为0的为一组,结果不为0的为1组 分别做^运算得到两个数x1 x2

题解:

class Solution {
    public int[] singleNumber(int[] nums) {
        //总体思路:把不同的两个数放在两个小组
        //如何分组?
        //由异或的性质 a^a = 0, a^0 = a
        //先把所有数值异或 得到结果x = x1^x2
        //再由因为x1!= x2 ,一定有一位为1, x&(-x)得到最低位比特为1的值 将这一位作为分组依据
        int x = 0;
        for(int e:nums){
           x=e^x;
        }//得到所有元素的异或和x
        int ground = x&(-x); //6的二进制是(0110)所以结果就是(0010)
        int x1 = 0;
        int x2 = 0;
        for(int e : nums){
           if((e & ground) == 0){ //位为0
              x1 =x1^ e;
           }else{
              x2 =x2^ e;
           }
        }
        return new int[]{x1,x2};
    }
}

面试题 05.06. 整数转换

整数转换。编写一个函数,确定需要改变几个位才能将整数A转成整数B

思路:对两个整数异或 判断有几个1。

or&(or -1) //消去or二进制表示的最低位的1

class Solution {
    public int convertInteger(int A, int B) {
        int or = A^B;
        //将问题转换为or中1的个数 因为不同位为1
        int cnt = 0;        
        while(or != 0){
           or = or&(or -1);
           cnt++;
        }
        return cnt;
    }
}

2.二分查找

704. 二分查找

思路:二分查找细节详解

class Solution {
    public int search(int[] nums, int target) {
        int low = 0;
        int high = nums.length - 1;
         int mid = 0;
        //假设target在[left right]中 显然结束循环的条件如果是
        while(low <= high){
             mid = (low + high)/2;
            if(nums[mid] > target){
                high = mid - 1;
            
            }else if(nums[mid] < target){
                  low = mid + 1;
            }else{
                return mid;
            }

        }
        return -1;
    }
}

3.双指针

977. 有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

思路:因为数组是一个递增的顺序 平方的最大值一定是在数组的两边。所以考虑从两个向中间遍历不断找平方的最大值。注意有负数。

class Solution {
    public int[] sortedSquares(int[] nums) {
        //最大值一定在两侧取到
        int n = nums.length;
        int []res = new int[n];
        int left = 0,right = n - 1,k = n - 1;
        while(left <= right && k >= 0){
            if(Math.abs(nums[left]) < Math.abs(nums[right])){
                res[k--] = nums[right] * nums[right];
                right--;
            }else{
                res[k--] = nums[left] * nums[left];
                left++;
            }
        }
        return res;
    }
}

209. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0

思路:滑动窗口

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        //left right表示一个窗口
        int left = 0;
        int right = 0;
        int minLen =Integer.MAX_VALUE;
        int sum = 0;
        while(right < nums.length){
                sum += nums[right];
                //寻找满足条件的最小左边界
                while(sum >= target){
                    //此时满足条件 记录此时的长度 并与最小长度比较
                     minLen = Math.min(minLen,right - left +1);
                     //缩减窗口 找最短的长度
                    sum -= nums[left];
                    left++;
                }
            	//此时的sum一定<target 扩大窗口
                right++;
        }
        //若没有连续大于target的子数组 minLen不发生变化 则返回0
        return minLen ==  Integer.MAX_VALUE ? 0: minLen;
        
    }
}

3. 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

思路:

​ 找出从每一个字符开始的,不包含重复字符的最长子串,那么其中最长的那个字符串即为答案。

​ 用左指针指向每个开始的子字符 右指针不断向后遍历 若出现了重复元素记录之前的长度,直到出现重复元素为止。结束循环

​ 因为右指针停止循环的位置之前都没有出现重复元素,故下次直接从right开始遍历即可

​ 左指针向前移动一个单位,(注意:此时若不是第一个元素 需要把上一个的元素从set中移除)

改进思路(待实现):因为循环做了许多无效的循环 发现有重复字符时,可以直接把左指针移动到第一个重复字符的下一个位置即可。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        if(s == null||s==""){
            return 0;
        }
        if(s.length() == 1){
            return 1;
        }
        int left = 0;
        int right = 0;
        int maxLen = 0;
        Set<Character> set = new HashSet<>();
        char []chars = s.toCharArray();
        int len = chars.length;
        
        for(;left < len ; left++){
            //将上一个left的字符移除
            if(left != 0){
                set.remove(chars[left - 1]);
            }
            //到达right之前的元素一定是没有重复元素的 所以right无需移动
            while(right < len && !set.contains(chars[right])){
                set.add(chars[right]);
                right++;
            }
            maxLen = Math.max(maxLen,right - left);
        }
        return maxLen;
    }
}

4.模拟

59. 螺旋矩阵 II

Given a positive integer n, generate an n x n matrix filled with elements from 1 to n2 in spiral order.

思路:循环模拟 参考–Spiral Matrix II (模拟法,设定边界,代码简短清晰) - 螺旋矩阵 II

class Solution {
    public int[][] generateMatrix(int n) {
        //定义上下左右边界值
        int [][] matrix = new int[n][n];
        int top = 0;
        int bottom = n - 1;
        int left = 0;
        int right = n -1;
        int num = 1;
        int square = n * n;
        while(num <= square){
            //从左到右填充 [left,right]
            for(int i = left;i <= right;i++){
                matrix[top][i] = num;
                num++;
            }
            //对拐角处进行处理 也可以理解为缩小边界
            top++;
            //右边界从上到下填充
            for(int i = top;i <= bottom;i++){
                matrix[i][right] = num;
                num++;
            }
            right--;
            //下边界从右到左填充
            for(int i = right;i >= left;i--){
                matrix[bottom][i] = num;
                num++;
            }
            bottom--;
            //左边界从下到上填充
            for(int i = bottom;i >= top;i--){
                matrix[i][left] =num;
                num++;
            }
            left++;
        }
        return matrix;
    }
}

5.数学

1716. 计算力扣银行的钱

Hercy wants to save money for his first car. He puts money in the Leetcode bank every day.

He starts by putting in $1 on Monday, the first day. Every day from Tuesday to Sunday, he will put in $1 more than the day before. On every subsequent Monday, he will put in $1 more than the previous Monday.(比前一个周一存的钱数多1)
Given n, return the total amount of money he will have in the Leetcode bank at the end of the nth day.

思路:理解题意,等差数列求和问题,重温等差数列求和公式。。

class Solution {
    //等差数列公式: an = a1 +  (n-1) * d
    //等差数列求和公式: Sn = (a1 + an) * n / 2
    //显然每一个完整的周会比上一个完整的周多存7 设第一个完整的周为a1 则有an= a1 + (n-1) * 7 
    public int totalMoney(int n) {
        int weekNum = n / 7;         //有几个完整的一周
        int dayNum = n % 7;              //不完整的周有几天
        int a1 = (1+7)*7/2;         //第一个完整的周存的钱
        int an = a1 +(weekNum-1)*7; //第weekNum个完整的周存的钱
        int s1 = (a1+an)*weekNum /2;
        //还有不完整的周所存钱数
        //显然 不完整周的周存的钱为 weekNum+1
        //而接下来的每一天存的钱比前一天多1 公差为1 的等差数列求和问题
        int b1 = weekNum +1;
        int bn = b1 + (dayNum-1)*1;
        int s2 = (b1+bn)*dayNum / 2;
        return s1 + s2;
    }
}

142. 环形链表 II

在这里插入图片描述

public class Solution {
    public ListNode detectCycle(ListNode head) {
        //先判断有无环
        if(head == null || head.next ==null){
            return null;
        }
        ListNode slow , fast;
        slow = fast = head;
        while(fast.next!=null && fast.next.next!=null){
            slow = slow.next;
            fast = fast.next.next;
            if(fast == slow){
                //有环
                fast = head;
                while(fast != slow){
                    fast = fast.next;
                    slow = slow.next;
                }
                return slow;
            }
        }
        return null;
        
        
    }
}

6.哈希

242. 有效的字母异位词

思路:简单哈希

class Solution {
    public boolean isAnagram(String s, String t) {
        int [] lettersNum = new int[26];
        char [] c1 = s.toCharArray();
        char [] c2 = t.toCharArray();
        for(int i = 0;i < s.length();i++){
            char c = c1[i];
            lettersNum[ c -'a']++;
        }
        for(int i = 0;i < t.length();i++){
            char c =c2[i];
            lettersNum[ c -'a']--;
        }
        for(int k = 0;k < 26;k++){
            if(lettersNum[k] != 0){
                return false;
            }
        }
        return true;
    }
}

349. 两个数组的交集

思路:利用set集合的不存在重复元素的特性找交集

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> num1Set = new HashSet<Integer>();
        Set<Integer> num2Set = new HashSet<Integer>();
        for(int i:nums1){
            num1Set.add(i);
        } 
        for(int i:nums2){
             num2Set.add(i);
        }
        return  subSection(num1Set,num2Set);

    }
    public int[] subSection(Set<Integer> set1,Set<Integer> set2){
        Set<Integer> minSet;
        Set<Integer> bigSet;
        Set<Integer> intersectionSet = new HashSet<Integer>();
        int len = 0;
        if(set1.size() > set2.size()){
            minSet = set2;
            bigSet = set1;
            
        }else{
            minSet = set1;
            bigSet = set2;
           
        }
        for(int i:minSet){
            if(bigSet.contains(i)){
                intersectionSet.add(i);
            }
        }
        int[] intersection = new int[intersectionSet.size()];
        for(int i:intersectionSet){
            intersection[len++] = i;
        }
        return intersection;

    }
}

1. 两数之和

思路:HashMap 保存键值对<元素值,元素下标>

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int res [] = new int [2];
        if(nums ==null || nums.length == 0){
            return res;
        }
        //一次性维护遍历过的元素值和它的下标 考虑到可以用HashMap
        Map<Integer,Integer> hashMap = new HashMap<>();
        for(int i = 0;i < nums.length;i++){
            //遍历每一个值 计算target - 当前值的结果,若结果已经存在在哈希表中,那么返回下标,并记录当前元素的下标。
            int temp = target - nums[i];
            if(hashMap.containsKey(temp)){
               res[0] = i;
               res[1] = hashMap.get(temp);
            }
            hashMap.put(nums[i],i);
        }    
        return res;

    }
}

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

思路:先计算 前两个数组nums1 和nums2的各个元素之和并将和记录为数组的键,出现的次数记为值。然后遍历num3和nums4,计算每一个元素的和,并查看 前两个数组的和中有无和为 - (num3[] + nums4[])的键,若有则记录次数

次数是将map中的次数进行累加,因为map中的键的每一个值和num3 nums4的一个和共同构成一个元组,而一个键对应出现次数代表有几种不同的元组。

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        Map<Integer,Integer> map = new HashMap<>();
        for(int i = 0;i < nums1.length;i++){
            for(int j = 0;j < nums2.length;j++ ){
                int sum = nums1[i] + nums2[j];
                if(map.containsKey(sum)){
                    map.put(sum , map.get(sum) + 1);
                }else{
                    map.put(sum,1);
                }
            }
        }
        int count = 0;
        for(int i = 0;i < nums3.length;i++){
            for(int j = 0;j < nums4.length;j++ ){
                int sum = nums3[i] + nums4[j];
                if(map.containsKey(0-sum)){
                  //仔细思考
                   count += map.get(0-sum);
                }
            }
        }
        return count;

    }
}

219. 存在重复元素 II

Given an integer array nums and an integer k, return true if there are two distinct indices i and j in the array such that nums[i] == nums[j] and abs(i - j) <= k.

思路
1.从前向后遍历 若存在相等的元素 2.看下标满足i - j <=k 满足返回true
3.若不存在相等的元素,则将元素和下标存入哈希表中,若存在相等的元素 但不满足下标关系 保存下标最大的那个

如果在下标 i 之前存在多个元素都和 nums[i] 相等,为了判断是否存在满足 nums[i]=nums[j] 且 i−j≤k 的下标 j,应该在这些元素中寻找下标最大的元素,将最大下标记为 j,判断i−j≤k 是否成立。

如果i−j≤k,则找到了两个符合要求的下标 j 和 i;如果i−j>k,则在下标 i 之前不存在任何元素满足与 nums[i] 相等且下标差的绝对值不超过 k,理由如下:

假设存在下标 j’ 满足 j’ < j < i。
且nums[j’ ]=nums[j]=nums[i],则 i - j’ > i - j,由于 i - j > k,因此必有 i - j’ > k

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        //1.从前向后遍历 若存在相等的元素 
        //看下标满足i - j <=k 满足返回true
        Map<Integer,Integer> map = new HashMap<>();
        for(int i = 0;i < nums.length;i++){
            int temp = nums[i];
            if(map.containsKey(temp) && (i - map.get(temp) <= k)){
                return true;
            }
            //put在此映射中关联指定值与指定键。如果该映射以前包含了一个该键的映射关系,则旧值被替换。
            //始终保存的都是重复元素的最大下标, 
            map.put(temp,i);
        }
         return false;
    }
   
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于力扣刷题C++常用操作,我可以给你一些常见的操作和技巧: 1. 使用 STL 容器和算法库:STL(Standard Template Library)是 C++ 标准库中的一个重要组成部分,包含了许多常用的容器和算法。在力扣刷题中,使用 STL 可以大大提高代码的效率和可读性。例如,vector 可以用来存储动态数组,sort 可以用来排序等等。 2. 使用 auto 关键字:auto 关键字可以自动推导变量类型,可以减少代码量和提高可读性。例如,auto x = 1; 可以自动推导出 x 的类型为 int。 3. 使用 lambda 表达式:lambda 表达式是 C++11 中引入的一种匿名函数,可以方便地定义一些简单的函数对象。在力扣刷题中,使用 lambda 表达式可以简化代码,例如在 sort 函数中自定义比较函数。 4. 使用位运算:位运算是一种高效的运算方式,在力扣刷题中经常会用到。例如,左移运算符 << 可以用来计算 2 的幂次方,右移运算符 >> 可以用来除以 2 等等。 5. 使用递归:递归是一种常见的算法思想,在力扣刷题中也经常会用到。例如,二叉树的遍历、链表的反转等等。 6. 使用 STL 中的 priority_queue:priority_queue 是 STL 中的一个容器,可以用来实现堆。在力扣刷题中,使用 priority_queue 可以方便地实现一些需要维护最大值或最小值的算法。 7. 使用 STL 中的 unordered_map:unordered_map 是 STL 中的一个容器,可以用来实现哈希表。在力扣刷题中,使用 unordered_map 可以方便地实现一些需要快速查找和插入的算法。 8. 使用 STL 中的 string:string 是 STL 中的一个容器,可以用来存储字符串。在力扣刷题中,使用 string 可以方便地处理字符串相关的问。 9. 注意边界条件:在力扣刷题中,边界条件往往是解决问的关键。需要仔细分析目,考虑各种边界情况,避免出现错误。 10. 注意时间复杂度:在力扣刷题中,时间复杂度往往是评判代码优劣的重要指标。需要仔细分析算法的时间复杂度,并尽可能优化代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值