Leetcode 小白刷题记录C++版

本文记录了作者使用C++在LeetCode上刷题的心得体会,涵盖字符串、数组、链表、栈和队列、排序、树、二分查找、回溯、哈希和动态规划等多个领域的经典问题,通过实例解析解题策略和关键代码实现。
摘要由CSDN通过智能技术生成


最近想系统的刷一刷题,所以在此记录一下以便于自己巩固和复习。如有问题请指正。

字符串

反转字符串

class Solution {
   
public:
    void reverseString(vector<char>& s) {
   
        int len = s.size();
        char temp;
        for(int i=0; i<len/2; i++){
   
            temp = s[i];
            s[i] = s[len-i-1];
            s[len-i-1] = temp;
        }
    }
};

双指针

class Solution {
   
public:
    void reverseString(vector<char>& s) {
   
        for(int l=0,r=s.size()-1;l<r;l++,r--)swap(s[l],s[r]);
    }
};

字符串转换整数 (atoi)

class Solution {
   
public:
    int myAtoi(string s) {
   
        long long result = 0;
        if(!s.size()) return 0;
        bool sign = true;
        int i = 0;
        while (s[i] == ' '){
   i++;}
        if (s[i] == '-'){
   
            sign = false;
            i++;
        }else if (s[i] == '+'){
   //注意这里不能是if,考虑-+ +-的情况
            i++;
        }
        if (s[i] == 0){
   
            return 0;
        }
        while(i < s.size()){
   
            if(s[i] < '0' or s[i] > '9'){
   
                break;
            }
            result = result * 10 + (s[i] - '0');
            if(result > INT_MAX){
   
                return sign ? INT_MAX : -INT_MAX-1;
            }
            i++;
        }
        return sign ? result : -result;
    }
};

最长公共前缀

横向扫描法

class Solution {
   
public:
    string longestCommonPrefix(vector<string>& strs) {
   
        if(!strs.size()){
   
            return "";
        }
        string prefix = strs[0];
        for (int i = 1; i < strs.size(); i++){
   
            prefix = longestCommonPrefix(prefix, strs[i]);
            if(!prefix.size()){
   
                return "";
            }
        }
        return prefix;
    }
    string longestCommonPrefix(const string& str1, const string& str2) {
   
        int len = min(str1.size(), str2.size());
        int i = 0;
        while(i < len && str1[i] == str2[i]){
   
            i++;
        }
        return str1.substr(0, i);
    }
};

纵向扫描法

class Solution {
   
public:
    string longestCommonPrefix(vector<string>& strs) {
   
        if(strs.size() == 0){
   
            return "";
        }
        bool same;
        for (int i = 0; i < strs[0].size(); i++){
   
            char c = strs[0][i];
            same = true; 
            for (int j = 1; j < strs.size(); j++){
   
                if (strs[j][i] != c || i == strs[j].size()){
   
                    //如果遇到不同的字符或某个字符串已经遍历结束
                    return strs[0].substr(0,i);
                }
            }
        }
        return strs[0];
    }
};

无重复字符的最长子串

https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

下面解法还有点难理解

class Solution {
   
public:
    int lengthOfLongestSubstring(string s) {
   
        int i=-1,result = 0;
        vector<int> dict(128,-1);
        for(int j=0;j<s.size();j++){
   
            i=max(i,dict[s[j]]);
            dict[s[j]]=j;
            result=max(result,j-i);
        }
        return result;
    }
};

数组

删除排序数组中的重复项

给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
给定 nums = [0,0,1,1,1,2,2,3,3,4],
函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。你不需要考虑数组中超出新长度后面的元素。

class Solution {
   
public:
    int removeDuplicates(vector<int>& nums) {
   
        if (nums.size()<=1){
   
            return nums.size();
        }
        int i=0;
        for(int j=1;j<nums.size();j++){
   
            if (nums[j]!=nums[i]){
   
            	//相当于i维持新数组下标,每遇到一个新元素, 就把其复制到新数组
                nums[++i]=nums[j];
            }
        }
        return i+1;
    }
};

移除元素

class Solution {
   
public:
    int removeElement(vector<int>& nums, int val) {
   
        int i=0;
        for(int j=0; j<nums.size(); j++){
   
            if(nums[j]!=val){
   
                nums[i++]=nums[j];
            }
        }
        return i;
    }
};

数组中重复的数字

class Solution {
   
public:
    int findRepeatNumber(vector<int>& nums) {
   
        if(nums.size()<=1){
   
            return -1;
        }
        unordered_set<int> cache;
        for(int i=0;i<nums.size();i++){
   
            if(cache.count(nums[i])){
   
                return nums[i];
            }
            cache.insert(nums[i]);
        }
        return -1;

    }
};

合并两个有序数组

https://leetcode-cn.com/problems/merge-sorted-array/

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。

从后向前比较

class Solution {
   
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
   
        int i = m-1, j = n-1;
        while(i+j+1 >= 0) {
   
            if(j < 0 || (i >= 0 && nums1[i] >= nums2[j])){
   
                nums1[i+j+1] = nums1[i];
                i--;
            }else if(i < 0 || (j >= 0 && nums1[i] < nums2[j])){
   
                nums1[i+j+1] = nums2[j];
                j--;
            }
        }
    }
};

先copy后sort

class Solution {
   
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
   
        for (int i=m,j=0; i<m+n; i++,j++){
   
            nums1[i] = nums2[j];
        }
        sort(nums1.begin(), nums1.end());
    }
};

扑克牌中的顺子

https://leetcode-cn.com/problems/bu-ke-pai-zhong-de-shun-zi-lcof

从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。
示例 2:输入: [0,0,1,2,5]
输出: True

注意:[0,0,1,2,5] 相当于[1,2,3,4,5]
分析:可以先排序,计算joker数量, 如果除了jokder还有重复值,返回false, 最后判断除了jodker的 首尾元素之差是不是小于5

class Solution {
   
public:
    bool isStraight(vector<int>& nums) {
   
        sort(nums.begin(), nums.end());
        int joker = 0;   
        for(int i=0;i<4;i++){
   
            if(nums[i] == 0){
   
                joker++;
            }else if(nums[i] == nums[i+1]){
   
                return false;
            }
        }
        return nums[4] - nums[joker] < 5;
    }
};

买卖股票的最佳时机

https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/

该题并没要求找出何时买卖的时机,只求最大利润
所以只需每次迭代更新谷底和最大利润值

class Solution {
   
public:
    int maxProfit(vector<int>& prices) {
   
        if (prices.size() == 0){
   
            return 0;
        }
        int lowPrice = prices[0];
        int profit = 0; 
        for(int i=1; i< prices.size(); i++){
   
            if(prices[i] < lowPrice){
   
                lowPrice = prices[i];
            }
            profit = max(profit, prices[i] - lowPrice);
        }
        return profit;
    }
};

链表

链表逆置

https://leetcode-cn.com/problems/reverse-linked-list/

反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

就地逆置

class Solution {
   
public:
    ListNode* reverseList(ListNode* head) {
   
        ListNode * next;
        ListNode * new_head = nullptr;
        while(head){
   
            next = head->next;
            head->next = new_head;
            new_head = head;
            head = next;
        }
        return new_head;

    }
};

递归

class Solution {
   
public:
    ListNode* reverseList(ListNode* head) {
   
        if (head == NULL || head->next == NULL){
   
            return head;
        }
        ListNode* new_head = reverseList(head->next);
        head->next->next=head; //例: 1->2<-3<-4<-5
        head->next = NULL;
        return new_head;
    }
};

环形链表 II

快慢指针法

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
   
public:
    ListNode *detectCycle(ListNode *head
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值