力扣刷题合集(持续更新)

在过去一年的时间里, 我在力扣这个平台刷了很多很多的题, 后面就转战牛客, 蓝桥云课等竞赛平台了, 现在我以此篇文章来对力扣刷题做个总结。由于本人水平有限, 仅仅做经验分享 ,但还是希望这篇文章对你有所帮助, (语言的话, 这次就选择C++和Java, 但是本人很少用Java刷题, 因此会在题目中介绍的java的相关方法, 也就当学习了)

学过面向对象都知道, 力扣是采用核心代码模式, 只用去实现对应类中的方法即可, 那我们直接开讲吧(由于题目可能会有很多, 所以就不贴题目, 只分享思路和代码)

知识点讲解参考: Hello算法, Javase 1.8

1. 两数之和

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]

一种思路是两层for循环, 另一种就是用哈希表key-value

对于第二种写法, 我们使用哈希表一遍遍历, 一遍存储{nums[i], i}, 顺便去检查哈希表里面是否存在target - nums[i], 如果存在就返回 索引数对

哈希表(hash table)又称散列表,它通过建立键 key 与值 value 之间的映射,实现高效的元素查询。具体而言,我们向哈希表中输入一个键 key ,则可以在O(1)时间内获取对应的值 value

哈希表用法: 
/* 初始化哈希表 */
Map<Integer, String> map = new HashMap<>();

/* 添加操作 */
// 在哈希表中添加键值对 (key, value)
map.put(12836, "小哈");
map.put(15937, "小啰");
map.put(16750, "小算");
map.put(13276, "小法");
map.put(10583, "小鸭");

/* 查询操作 */
// 向哈希表中输入键 key ,得到值 value
String name = map.get(15937);

/* 删除操作 */
// 在哈希表中删除键值对 (key, value)
map.remove(10583);

/*Returns true if this map contains a mapping for the specified key.*/
map.containKey(12836)
C++:  
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> mp; int idx=-1;
        for(auto& x:nums){
            idx++;
            if(mp.find(target-x)!=mp.end()){
                return {mp[target-x],idx};
            }
            mp[x]=idx;
        }
        return {};
    }
};
JAVA:  
class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> mp=new HashMap<>();
        for(int i=0;i<nums.length;i++){
            int tmp=target-nums[i];
            if(mp.containsKey(tmp)){
                return new int[]{mp.get(tmp),i};
            }
            mp.put(nums[i],i);
        }
        return new int[0];
    }
}

 2. 两数相加

在链表的首位添加一个节点

链表(linked list)是一种线性数据结构,其中的每个元素都是一个节点对象,各个节点通过“引用”相连接。引用记录了下一个节点的内存地址,通过它可以从当前节点访问到下一个节点
链表的设计使得各个节点可以分散存储在内存各处,它们的内存地址无须连续

JAVA里面是没有指针, 只有引用

链表用法: 
/* 链表节点类 */
class ListNode {
    int val;        // 节点值
    ListNode next;  // 指向下一节点的引用
    ListNode(int x) { val = x; }  // 构造函数
}
/* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */
// 初始化各个节点
ListNode n0 = new ListNode(1);
ListNode n1 = new ListNode(3);
ListNode n2 = new ListNode(2);
ListNode n3 = new ListNode(5);
ListNode n4 = new ListNode(4);
// 构建节点之间的引用
n0.next = n1;
n1.next = n2;
n2.next = n3;
n3.next = n4;
C++:  
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *v = new ListNode(0), *cur = v;
        int sum = 0;
        while (l1 || l2 || sum) {
            if (l1)
                sum += l1->val, l1 = l1->next;
            if (l2)
                sum += l2->val, l2 = l2->next;
            cur->next = new ListNode(sum % 10);
            cur = cur->next;
            sum /= 10;
        }
        return v->next;
    }
};
Java:  
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode v = new ListNode(0);
        ListNode cur = v;
        int carry = 0;
        while (l1 != null || l2 != null || carry != 0) {
            int sum = carry;
            if (l1 != null) {
                sum += l1.val;
                l1 = l1.next;
            }
            if (l2 != null) {
                sum += l2.val;
                l2 = l2.next;
            }
            cur.next = new ListNode(sum % 10);
            cur = cur.next;
            carry = sum / 10;
        }
        return v.next;
    }
}

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

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

滑动窗口维护:
使用两个指针l和r表示窗口的左右边界
l指向当前无重复子串的起始位置
r不断向右移动扩展窗口
核心逻辑:
每当r向右移动一位,检查新字符s[r]是否在窗口[l,r-1]中出现过
如果出现过(f=1),就将l移动到重复字符的下一个位置(j+1)
如果没出现过(f=0),就更新最大长度mx

可以使用哈希表进行优化

C++: 
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<int,int> mp;
        int L=0, mx_len=0, n=s.size();
        for(int r=0;r<n;r++){
            char c=s[r];
            if(mp.find(c)!=mp.end()&&mp[c]>=L){
                L=mp[c]+1;
            }
            mp[c]=r;
            mx_len=max(mx_len,r-L+1);
        }
        return mx_len;
    }
};
Java:  
class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Character, Integer> mp = new HashMap<>();
        int L = 0, mx_len = 0, n = s.length();
        for (int r = 0; r < n; r++) {
            char c = s.charAt(r);
            if (mp.containsKey(c) && mp.get(c) >= L) {
                L = mp.get(c) + 1;
            }
            mp.put(c, r); //维护当前字符的右边界
            mx_len = Math.max(mx_len, r - L + 1);
        }
        return mx_len;
    }
}

 5. 最长回文子串

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

定义一个函数 dfs(i, j) 来判断 s[i..j] 是否为回文串,并用记忆化表 dp[i][j] 来存储中间结果。
然后我们遍历所有可能的子串 s[i..j],当 dfs(i, j) 为真时,尝试更新最长的回文子串

class Solution {
    private Boolean[][] memo;
    public String longestPalindrome(String s) {
        int n = s.length();
        memo = new Boolean[n][n];
        int mx_len = 0;
        int st = 0;
        for (int i = 0; i < n; ++i) {
            for (int j = i; j < n; ++j) {
                if (dfs(s, i, j)) {
                    if (j - i + 1 > mx_len) {
                        mx_len = j - i + 1;
                        st = i;
                    }
                }
            }
        }
        return s.substring(st, st + mx_len);
    }
    private boolean dfs(String s, int i, int j) {
        if (i >= j) return true;
        if (memo[i][j] != null) return memo[i][j];
        if (s.charAt(i) != s.charAt(j)) {
            memo[i][j] = false;
        } else {
            memo[i][j] = dfs(s, i + 1, j - 1);
        }
        return memo[i][j];
    }
}

 6. Z 字形变换

区分:StringBuilder是线程不安全的,StringBuffer是线程安全的(所有方法都用 synchronized 修饰),前者在单线程中使用, 后者在多线程中使用, 前者性能更高, 后者确保线程安全

class Solution {
    public String convert(String s, int numRows) {
        if(numRows==1) return s;
        StringBuilder[] r=new StringBuilder[numRows];
        for(int i=0;i<numRows;i++){
            r[i]=new StringBuilder();
        }
        boolean f=false;
        int cur_r=0;
        for(char c:s.toCharArray()){
            r[cur_r].append(c);
            if(cur_r==0||cur_r==numRows-1){
                f=!f;
            }
            cur_r+=f?1:-1;
        }
        StringBuilder res=new StringBuilder();
        for(StringBuilder x:r){
            res.append(x);
        }
        return res.toString();
    }
}
class Solution {
public:
    string convert(string s, int len) {
        if(len==1) return s;
        vector<string> ans(len);
        bool f=false; int n=s.size();
        int row=0;
        for(int i=0;i<n;i++){
             ans[row]+=s[i];
             if(row==0||row==len-1) f=!f;
             row+=f?1:-1;
        }
        string res="";
        for(auto& x:ans) res+=x;
        return res;
    }
};

 7. 整数反转

解题思路:直接翻转即可,注意不要超过int

class Solution {
public:
    int reverse(int x){
        long long reversed = 0; 
            while (x != 0) {
            int digit = x % 10; 
            reversed = reversed * 10 + digit; 
            if (reversed > INT_MAX || reversed < INT_MIN){ 
                return 0;
            }
            x /= 10;
        }
        return reversed;
    }
};
class Solution {
public:
    int reverse(int x){
        long long reversed = 0; 
            while (x != 0) {
            int digit = x % 10; 
            reversed = reversed * 10 + digit; 
            if (reversed > INT_MAX || reversed < INT_MIN){ 
                return 0;
            }
            x /= 10;
        }
        return reversed;
    }
};

 8. 字符串转换整数 (atoi)

 解题思路:类似于C++中的stoi函数

class Solution {
    public int myAtoi(String s) {
        long ans=0;
        int start=0,n=s.length();
        while(start<n&&s.charAt(start)==' '){
            start++;
        }
        if(start==n) return 0;
        int f=1;
        if(s.charAt(start)=='-'){
            f=-1;
            start++;
        }else if(s.charAt(start)=='+'){
            start++;
        }
        for(int i=start;i<n&&Character.isDigit(s.charAt(i));i++){
            ans=ans*10+f*(s.charAt(i)-'0');
            if(ans>0&&ans>Integer.MAX_VALUE){
                return Integer.MAX_VALUE;
            }
            if(ans<0&&ans<Integer.MIN_VALUE){
                return Integer.MIN_VALUE;
            }
        }
        return (int)ans;
    }
}
class Solution {
public:
    int myAtoi(string s) {
       long long ans=0;
       int start=0;
       while(start<s.length() && s[start]==' ') start++;
       if(start==s.length())  return 0;
       int sign=1;
       if(s[start]=='-') sign=-1,start++;
       else if(s[start]=='+') start++;
       for(int i=start;i<s.length()&&isdigit(s[i]);i++)
       {
           ans=ans*10+sign*(s[i]-'0');
           if(ans>0&&ans>=INT_MAX) return INT_MAX;
           if(ans<0&&ans<=INT_MIN) return INT_MIN;
       }
       return ans;
    }
};

9. 回文数 

回文数判断 

class Solution {
    public boolean isPalindrome(int x) {
        if(x<0) return false;
        long tmp=x,res=0;
        while(tmp>0){
            res=res*10+tmp%10;
            tmp/=10;
        }
        if(res==x) return true;
        return false;
    }
}
class Solution {
public:
    bool isPalindrome(int x) {
        if (x < 0){
            return false;
        }
        long long m = x;
        long long i = 0;
        while (m) {
            i = i * 10 + m % 10;
            m /= 10;
        }
        if (i == x){
            return true;
        }else{
            return false;
        }
    }
};

11. 盛最多水的容器

class Solution {
    public int maxArea(int[] height) {
        int ans=0;
        int left=0,right=height.length-1;
        while(left<right){
            ans=Math.max(ans,Math.min(height[left],height[right])*(right-left));
            if(height[left]<height[right]) left++;
            else right--;
        }
        return ans;
    }
}

class Solution {
public:
    int maxArea(vector<int>& height) {
      int ans=0;
      int l=0,r=height.size()-1;
      while(l<r)
      {
        ans=max(ans,min(height[l],height[r])*(r-l));
        if(height[l]<height[r]) l++;
        else r--;
      }
      return ans;
    }
};

 未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值