Leetcode面试经典150题【数组/字符串部分】【已完成】

总结

值得再看的点:

T88 合并两个有序数组 简单模拟 边界条件

// 2024.8.24
class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int p1=0, p2=0, p=0;
        int ans[205] = {0};
        while (p1 < m || p2 < n){
            if (p1 >= m || m == 0) {
                while (p2 < n) ans[p++] = nums2[p2++];
                break;
            }
            if (p2 >= n || n == 0){
                while (p1 < m) ans[p++] = nums1[p1++];
                break;
            }
            if (nums1[p1] <= nums2[p2])
                ans[p++] = nums1[p1++];
            else
                ans[p++] = nums2[p2++];
        }
        for (int i=0; i<n+m; i++)
            nums1[i] = ans[i];
    }
};

T27 移除元素

// 2024.8.24
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int p1=0;
        int p2=0;
        int len = nums.size();
        while (p2 < len){
            if (nums[p2] != val) 
                nums[p1++] = nums[p2++];
            else p2++;
        }
        return p1;
    }
};

T26&80 删除有序数组的重复项(I & II)

// 2024.8.25
// TI
class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int len = nums.size();
        int p = 1;
        int current_val = nums[0];
        int pos = 1;
        while (p < len){
            if (current_val == nums[p]){ // 放弃这个数
                p++;
                continue;
            }
            // 要这个数
            current_val = nums[p++];
            nums[pos++] = current_val;
        }
        return pos;
    }
};

//TII
class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int len = nums.size();
        if (len <= 2) return len;
        int pos_insert = 2; //前两个不变
        int pos_search = 2;
        int current_val_st = nums[0] == nums[1]? 0:1;
        int current_val = nums[pos_search - 1];
        while (pos_search < len){
            if (nums[pos_search] == current_val){
                if (pos_search - current_val_st >= 2) pos_search++;
                else {
                    nums[pos_insert++] = current_val;
                    pos_search++;
                }
            }
            else{
                current_val = nums[pos_search];
                current_val_st = pos_search++;
                nums[pos_insert++] = current_val;
            }
        }
        return pos_insert;
    }
};

T169 多数元素

// 2024.8.26
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int pos = floor(nums.size() / 2);
        sort(nums.begin(), nums.end());
        return nums[pos];
    }
};

vector排序

T189 轮转数组

方法一:暴力模拟,时间复杂度O(n^2)

// 2024.8.26
class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int len = nums.size();
        while (k--){
            int tail = nums[len - 1];
            int p = len;
            while (--p > 0){
                nums[p] = nums[p - 1];
            }
            nums[0] = tail;
        }
    }
};

方法二:根据提示观察规律,使用反转数组(也可以不申请新内存空间,空间O(1)实现)

// 2024.8.26
class Solution {
public:
    const int maxlen = 1e5 + 1;
    void rotate(vector<int>& nums, int k) {
        int len = nums.size();
        if (len <= 1) return;
        k = k % len;
        int nums_reverse[maxlen];
        for (int i=0; i<len; i++)
            nums_reverse[i] = nums[len-i-1];
        int left, right, tmp;
        left = 0;
        right = k - 1;
        while (left <= right){
            nums[left] = nums_reverse[right];
            nums[right] = nums_reverse[left];
            left++;
            right--;
        }
        left = k;
        right = len - 1;
        while (left <= right){
            nums[left] = nums_reverse[right];
            nums[right] = nums_reverse[left];
            left++;
            right--;
        }
    }
};

8.27:

T121&122 买卖股票的最佳时机(I & II)

T121:

方法一:暴力枚举买入和卖出的天数,时间复杂度O(n^2)

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int tot_Days = prices.size(); // 总天数
        int max_prof = 0;
        for (int buy_day = 0; buy_day < tot_Days - 1; buy_day++){
            for (int sell_day = buy_day + 1; sell_day < tot_Days; sell_day++){
                max_prof = max(max_prof, prices[sell_day] - prices[buy_day]);
            }
        }
        return max_prof;
    }
};

方法二:空间换时间,记录截至当前天数的最低买入花费,以及在这之后卖出的最高收获

class Solution {
public:
    const int maxlen = 1e5 + 5;
    int maxProfit(vector<int>& prices) {
        int tot_Days = prices.size(); // 总天数
        if (tot_Days <= 1) return 0;
        int max_prof = 0;
        int min_before[maxlen]; // 在这一天之前(不含)买入的最低价
        int max_after[maxlen]; // 在这一天之后(含)卖出的最高价
        int p;

        min_before[1] = prices[0];
        p = 2;
        while (p < tot_Days){
            min_before[p] = min(prices[p - 1], min_before[p - 1]);
            p++;
        }

        p = tot_Days - 2;
        max_after[tot_Days - 1] = prices[tot_Days - 1];
        while (p > 0){
            max_after[p] = max(max_after[p + 1], prices[p]);
            p--;
        }

        int n = 1;
        for (int i = 1;i < tot_Days; i++)
            max_prof = max(max_prof, max_after[i] - min_before[i]);
            
        return max_prof;

    }
};

方法二补充:可以使用空间复杂度O(1)的解法,遍历一遍,只用一个变量维护目前为止的最低买入价格就好了。(官方题解)

T122:

dp,可以用滚动数组省内存

class Solution {
public:
    const int maxn = 3e4+5;
    int maxProfit(vector<int>& prices) {
        int len = prices.size();
        int f[maxn][2];
        f[0][0] = 0;
        f[0][1] = -prices[0];
        for (int i = 1; i < len; i++){
            f[i][0] = max(f[i-1][0], f[i-1][1] + prices[i]);
            f[i][1] = max(f[i-1][1], f[i-1][0] - prices[i]);
        }
        return f[len-1][0];
    }
};

题解中贪心的方法...

T134 加油站(思路、贪心)

//2024.9.1
class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int st = 0;
        int n = gas.size();
        while (st < n){
            while (st < n && gas[st] - cost[st] < 0)
                st++;
            if (st < n){
                // 开始判断这个点作为起点可不可行
                int current_id = st;
                int next_id = st==n-1? 0 : st + 1;
                int num = 1; // 经过了几站
                int val = gas[current_id] - cost[current_id];
                while (num < n){
                    current_id = next_id;
                    next_id = current_id == n - 1? 0 : current_id + 1;
                    val += gas[current_id] - cost[current_id];
                    if (val < 0) break;
                    num++;
                }
                if (num < n) 
                    st+= num;
                else 
                    return st;
            }
        }
        return -1;
    }
};

T135 分发糖果

感觉只能多试几个样例才能get到需要正反遍历

// 2024.9.3
class Solution {
public:
    int candy(vector<int>& ratings) {
        int sum = 0;
        int n = ratings.size();
        vector<int> cnt(n, 1);
        // 正向遍历
        for (int i = 1; i < n; i++){
            if (ratings[i] > ratings[i - 1]){
                cnt[i] = cnt[i - 1] + 1; //相邻高的要得到更多 
            }
        }
        // 反向遍历
        for (int i = n - 2; i >= 0; i--){
            if (ratings[i] > ratings[i + 1]){
                cnt[i] = max(cnt[i + 1] + 1, cnt[i]);
                // cout << cnt[i] << endl;
            }
        }
        
        for (int i = 0; i < n; i++)
            sum+= cnt[i];
        return sum;
    }
};

T42 接雨水

也是一道思路需要多试样例才能想清楚的。画图有用。

// 2024.09.03
class Solution {
public:
    int trap(vector<int>& height) {
        // 根据题解:每个点储存的雨水 取决于 左右的各自最大值
        int n = height.size();
        if (n <= 2) return 0;
        int left_max[n + 5];
        memset(left_max, -1, sizeof(left_max));// 记录当前位置左边最高值
        int sum = 0;
        left_max[0] = -1;
        for (int i = 1; i < n; i++){
            int tmp = max(left_max[i-1], height[i-1]);
            left_max[i] = tmp;
        }
        int right_max = height[n-1]; // 当前位置右边最高值
        for (int i = n-2; i >=0; i--){
            int tmp = min(left_max[i], right_max) - height[i];
            if (tmp > 0) sum += tmp;
            right_max = max(right_max, height[i]);
        }
        return sum;
    }
};

T28 找出字符串中第一个匹配项的下标

从这道题了解KMP字符串匹配算法。

参考链接:

KMP算法

求解next数组讲解视频

再写一遍

T68 文本左右对齐

耐心写的模拟题

//2024.9.6
class Solution {
public:
    vector<string> fullJustify(vector<string>& words, int maxWidth) {
        int tot = words.size();
        string current_line = "";
        int current_len = 0;
        int st = 0;//记录每一行起始单词的下标
        vector<string> ans;
        for (int i=0; i<tot; i++){
            if (current_len == 0){ // 一行的开头
                current_len += words[i].length();
                st = i;
            }
            else {
                if (current_len + 1 + words[i].length() <= maxWidth){
                    current_len += 1 + words[i].length();
                }
                else{ // 当前这一行已经满了,处理这一行的输出
                    int word_len = 0;
                    int word_num = i - st; // (i-1)-(st)+1
                    for (int j = st; j <= i - 1; j ++)
                        word_len += words[j].length();
                    int blank_num = maxWidth - word_len; // 这一行中的空格数
                    if (word_num == 1){
                        ans.insert(ans.end(),words[st] + string(blank_num, ' '));
                    }
                    else{
                        int blank_base = blank_num / (word_num - 1);
                        int blank_res = blank_num % (word_num - 1);
                        string line="";
                        for (int j = st; j < i - 1; j++){
                            line += words[j] + string(blank_base, ' ');
                            if (blank_res) {
                                line += " ";
                                blank_res--;
                            }
                        }
                        line += words[i - 1];
                        ans.insert(ans.end(), line);
                    }
                    
                    // 把当前的这个单词作为新一行的起点
                    current_len = words[i].length();
                    st = i;
                }
            }
        }
        if (current_len){
            string line = "";
            for (int j = st; j < tot - 1; j++){
                line += words[j] + " ";
            }
            line += words[tot - 1];
            while (line.length() < maxWidth) line+=" ";
            ans.insert(ans.end(), line);
        }
        return ans;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值