2022-8 刷题记录

01-01. 不同路径 II

class Solution {
private:
    int path[100][100];
    
public:
    int uniquePathsWithObstacles(const vector<vector<int>> &grid) {
        int n = grid.size(), m = grid[0].size();
        if (grid[0][0] == 1 || grid[n - 1][m - 1] == 1) return 0;
        path[0][0] = 1;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                if (grid[i][j] == 0) {
                    if (i > 0) path[i][j] += path[i - 1][j];
                    if (j > 0) path[i][j] += path[i][j - 1];
                }
            }
        }
        return path[n - 1][m - 1];
    }
};
class Solution {
private:
    int path[2][100];

public:
    int uniquePathsWithObstacles(const vector<vector<int>> &grid) {
        int n = grid.size(), m = grid[0].size();
        if (grid[0][0] == 1 || grid[n - 1][m - 1] == 1) return 0;
        path[0][0] = 1;
        for (int i = 0, cur = 0, pre = 1; i < n; ++i, cur ^= 1, pre ^= 1) {
            for (int j = 0; j < m; ++j) {
                if (i != 0 || j != 0) {
                    path[cur][j] = 0;
                }
                if (grid[i][j] == 0) {
                    if (i > 0) path[cur][j] += path[pre][j];
                    if (j > 0) path[cur][j] += path[cur][j - 1];
                }
            }
        }
        return path[(n & 1) ^ 1][m - 1];
    }
};
class Solution {
private:
    int path[100];

public:
    int uniquePathsWithObstacles(const vector<vector<int>> &grid) {
        int n = grid.size(), m = grid[0].size();
        if (grid[0][0] == 1 || grid[n - 1][m - 1] == 1) return 0;
        path[0] = 1;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                if (grid[i][j] == 1){
                    path[j] = 0;
                } else if (j > 0) {
                    path[j] += path[j - 1];
                }
            }
        }
        return path[m - 1];
    }
};

01-02 生成每种字符都是奇数个的字符串

class Solution:
    def generateTheString(self, n: int) -> str:
        return 'a' * n if n & 1 else 'a' * (n - 1) + 'b'
class Solution {
public:
    string generateTheString(int n) {
        return (n & 1) ? string(n, 'a') : string(n - 1, 'a') + 'b';
    }
};

02-01 排序链表

class Solution {
private:
    ListNode *merge(ListNode *head1, ListNode *head2) {
        auto dummyHead = new ListNode();
        auto node = dummyHead;
        while (head1 && head2) {
            if (head1->val > head2->val) swap(head1, head2);
            node = node->next = head1;
            head1 = head1->next;
        }
        node->next = head1 ? head1 : head2;
        return dummyHead->next;
    }

    ListNode *sortList(ListNode *head, ListNode *tail) {
        if (head == nullptr) return nullptr;
        if (head->next == tail) {
            head->next = nullptr;
            return head;
        }
        auto slow = head, fast = head;
        while (fast != tail) {
            slow = slow->next, fast = fast->next;
            if (fast != tail) fast = fast->next;
        }
        return merge(sortList(head, slow), sortList(slow, tail));
    }

public:
    ListNode *sortList(ListNode *head) {
        return sortList(head, nullptr);
    }
};

03-01 连续子数组的最大和

class Solution {
public:
    int maxSubArray(vector<int> &nums) {
        int max_prev = nums[0];
        for (int i = 1, max_sum = nums[0]; i < nums.size(); ++i) {
            max_sum = max(max_sum + nums[i], nums[i]);
            max_prev = max(max_prev, max_sum);
        }
        return max_prev;
    }
};

04-01 情侣牵手

class Solution {
private:
    int parent[30];
    int n, cnt;

    int find(int x) {
        while (x != parent[x]) {
            parent[x] = parent[parent[x]];
            x = parent[x];
        }
        return x;
    }

    void unite(int x1, int x2) {
        int r1 = find(x1), r2 = find(x2);
        if (r1 != r2) {
            parent[r1] = r2;
            --cnt;
        }
    }

public:
    int minSwapsCouples(vector<int> &row) {
        n = cnt = row.size() >> 1;
        for (int i = 0; i < n; ++i) parent[i] = i;
        for (int i = 0; i < 2 * n; i += 2) {
            int p1 = row[i] >> 1, p2 = row[i + 1] >> 1;
            if (p1 != p2) unite(p1, p2);
        }
        return n - cnt;
    }
};

05-01 二叉树的最近公共祖先

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==nullptr || root==p || root==q) return root;
        auto nl = lowestCommonAncestor(root->left,p,q), nr = lowestCommonAncestor(root->right,p,q);
        if(nl && nr) return root;
        return nl?nl:nr;
    }
};

06-01 有重复字符串的排列组合

class Solution {
private:
    int n;
    int cnt[52 << 1];
    string path;
    vector<string> result;

    void dfs() {
        if (path.size() == n) {
            result.emplace_back(path);
            return;
        }
        for (int i = 0; i < 52; ++i) {
            if (cnt[i] == 0) continue;
            char ch = i < 26 ? i + 0x41 : i - 26 + 0x61;
            cnt[i]--;
            path.push_back(ch);
            dfs();
            cnt[i]++;
            path.pop_back();
        }
    }

public:
    vector<string> permutation(const string &s) {
        n = s.size();
        for (char ch: s) ++cnt[ch < 'a' ? ch - 0x41 : ch - 0x61 + 26];
        dfs();
        return result;
    }
};

07-01 使用最小花费爬楼梯

class Solution {
private:
    int dp[1005];

public:
    int minCostClimbingStairs(vector<int>& cost) {
        int n = cost.size();
        for (int i = 2; i <= n; i++) {
            dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
        }
        return dp[n];
    }
};

08-01 搜索旋转排序数组

class Solution {
public:
    int search(vector<int> nums, int target) {
        int lo = 0, hi = nums.size() - 1;
        while (lo <= hi) {
            int mi = (lo + hi) >> 1;
            if (nums[mi] == target) return mi;
            if (nums[lo] <= nums[mi]) {
                nums[lo] <= target && target < nums[mi] ? hi = mi - 1 : lo = mi + 1;
            } else {
                nums[mi] < target && target <= nums[hi] ? lo = mi + 1 : hi = mi - 1;
            }
        }
        return -1;
    }
};

09-01 移掉 K 位数字

class Solution {
public:
    string removeKdigits(string num, int k) {
        vector<char> stk;
        for (auto& digit: num) {
            while (!stk.empty() && stk.back() > digit && k) {
                stk.pop_back();
                k -= 1;
            }
            stk.push_back(digit);
        }

        while(k--) stk.pop_back();

        string ans = "";
        bool isLeadingZero = true;
        for (auto& digit: stk) {
            if (isLeadingZero && digit == '0') continue;
            isLeadingZero = false;
            ans += digit;
        }
        return ans == "" ? "0" : ans;
    }
};

10-01 二叉树的序列化与反序列化

class Codec {
public:
    string serialize(TreeNode* root) {
        stack<TreeNode*> st;
        st.push(root);
        string s;
        while(!st.empty()){
            TreeNode* cur=st.top();
            st.pop();
            if(cur==nullptr){
                s+="#,";
            }else{
                s+=to_string(cur->val)+",";
                st.push(cur->right);
                st.push(cur->left);
            }
        }
        s.pop_back();
        return s;
    }

    TreeNode* dfs(stringstream& ss){
        string tmp;
        getline(ss,tmp,',');
        if(tmp[0]=='#') return nullptr;
        auto node=new TreeNode(stoi(tmp));
        node->left=dfs(ss);
        node->right=dfs(ss);
        return node;
    }

    TreeNode* deserialize(string data_str) {
        stringstream ss(data_str);
        return dfs(ss);
    }
};

11-01 132 模式

class Solution {
public:
    bool find132pattern(vector<int>& nums) {
        int n = nums.size();
        if (n < 3) return false;

        int left_min = nums[0];
        multiset<int> right_all; 

        for (int k = 2; k < n; ++k)right_all.insert(nums[k]);

        for (int j = 1; j < n - 1; ++j) {
            if (left_min < nums[j]) {
                auto it = right_all.upper_bound(left_min);
                if (it != right_all.end() && *it < nums[j]) return true;
            }
            left_min = min(left_min, nums[j]);
            right_all.erase(right_all.find(nums[j + 1]));
        }

        return false;
    }
};

12-01 盛最多水的容器

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

13-01 3 的幂

class Solution {
public:
    bool isPowerOfThree(long long n) {
        if(n <= 0) return false;
        long long inc = 1;
        while(inc <= n){
            if(inc == n) return true;
            inc *= 3;
        }
        return false;
    }
};

14-01 字符串相乘

class Solution {
public:
    string multiply(string num1, string num2) {
        if (num1 == "0" || num2 == "0") {
            return "0";
        }
        string ans = "0";
        int m = num1.size(), n = num2.size();
        for (int i = n - 1; i >= 0; i--) {
            string curr;
            int add = 0;
            for (int j = n - 1; j > i; j--) {
                curr.push_back(0);
            }
            int y = num2.at(i) - '0';
            for (int j = m - 1; j >= 0; j--) {
                int x = num1.at(j) - '0';
                int product = x * y + add;
                curr.push_back(product % 10);
                add = product / 10;
            }
            while (add != 0) {
                curr.push_back(add % 10);
                add /= 10;
            }
            reverse(curr.begin(), curr.end());
            for (auto &c : curr) {
                c += '0';
            }
            ans = addStrings(ans, curr);
        }
        return ans;
    }

    string addStrings(string &num1, string &num2) {
        int i = num1.size() - 1, j = num2.size() - 1, add = 0;
        string ans;
        while (i >= 0 || j >= 0 || add != 0) {
            int x = i >= 0 ? num1.at(i) - '0' : 0;
            int y = j >= 0 ? num2.at(j) - '0' : 0;
            int result = x + y + add;
            ans.push_back(result % 10);
            add = result / 10;
            i--;
            j--;
        }
        reverse(ans.begin(), ans.end());
        for (auto &c: ans) {
            c += '0';
        }
        return ans;
    }
};

15-01 可被三整除的最大和

class Solution {
public:
    int dp[3];

    int maxSumDivThree(vector<int> &nums) {
        int n = nums.size();
        for (int i = 0, a, b, c; i < n; ++i) {
            a = dp[0] + nums[i];
            b = dp[1] + nums[i];
            c = dp[2] + nums[i];
            dp[a % 3] = max(dp[a % 3], a);
            dp[b % 3] = max(dp[b % 3], b);
            dp[c % 3] = max(dp[c % 3], c);
        }
        return dp[0];
    }
};

16-01 回文对

class Solution {
private:
    vector <string> wordsRev;
    unordered_map<string_view, int> indices;

public:
    int findWord(const string_view &s, int left, int right) {
        auto iter = indices.find(s.substr(left, right - left + 1));
        return iter == indices.end() ? -1 : iter->second;
    }

    bool isPalindrome(const string_view &s, int left, int right) {
        int len = right - left + 1;
        for (int i = 0; i < len / 2; i++) {
            if (s[left + i] != s[right - i]) return false;
        }
        return true;
    }

    vector <vector<int>> palindromePairs(vector <string> &words) {
        int n = words.size();
        for (string &word: words) {
            wordsRev.emplace_back(word);
            reverse(wordsRev.back().begin(), wordsRev.back().end());
        }
        for (int i = 0; i < n; ++i) indices.emplace(wordsRev[i], i);

        vector <vector<int>> ret;
        for (int i = 0; i < n; i++) {
            int m = words[i].size();
            if (!m) continue;
            string_view wordView(words[i]);
            for (int j = 0; j <= m; j++) {
                if (isPalindrome(wordView, j, m - 1)) {
                    int left_id = findWord(wordView, 0, j - 1);
                    if (left_id != -1 && left_id != i) ret.push_back({i, left_id});
                }
                if (j && isPalindrome(wordView, 0, j - 1)) {
                    int right_id = findWord(wordView, j, m - 1);
                    if (right_id != -1 && right_id != i) ret.push_back({right_id, i});
                }
            }
        }
        return ret;
    }
};

17-01 买卖股票的最佳时机

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int prev = 1e5, ans = 0;
        for(int p:prices){
            ans = max(ans, p - prev);
            prev = min(p, prev);
        }
        return ans;
    }
};

18-01 买卖股票的最佳时机 II

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

19-01 重复的DNA序列

class Solution {
private:
    int mask = (1 << 20) - 1;
    vector<string> ans;
    bitset<1 << 20> have;
    bitset<1 << 20> recorded;
public:
    vector<string> findRepeatedDnaSequences(const string &s) {
        int slide = 0, n = s.size();
        if (n <= 10) return ans;
        auto toInt = [](char ch) { return ch == 'A' ? 0 : ch == 'C' ? 1 : ch == 'G' ? 2 : 3; };
        for (int i = 0; i < 10; ++i)
            slide = (slide << 2) | toInt(s[i]);
        have.set(slide);
        for (int i = 0; i + 10 < n; ++i) {
            slide = ((slide << 2) | toInt(s[i + 10])) & mask;
            if (have.test(slide) && !recorded.test(slide)) {
                ans.emplace_back(s.substr(i + 1, 10));
                recorded.set(slide);
            }
            have.set(slide);
        }
        return ans;
    }
};

20-01 第二高的薪水

SELECT (SELECT DISTINCT Salary FROM Employee ORDER BY Salary DESC LIMIT 1 OFFSET 1)  AS SecondHighestSalary

21-01 下一个排列

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int i = nums.size() - 1, j = nums.size() - 1;
        while(i > 0 && nums[i-1] >= nums[i]) --i;
        if(i != 0){
            while(nums[j] <= nums[i - 1]) --j;
            swap(nums[i-1], nums[j]);
        }
        reverse(nums.begin() + i, nums.end());
    }
};

22-01 最短无序连续子数组

class Solution {
public:
    int findUnsortedSubarray(const vector<int> &nums) {
        int n = nums.size();
        vector<int> lo(n), hi(n);
        lo.back() = nums.back();
        for (int i = n - 2; i >= 0; --i) lo[i] = min(lo[i + 1], nums[i]);
        hi.front() = nums.front();
        for (int i = 1; i < n; ++i) hi[i] = max(hi[i - 1], nums[i]);
        int left = 0, right = n - 1;
        while (left < n && lo[left] >= nums[left]) left++;
        while (right >= 0 && hi[right] <= nums[right]) right--;
        return max(right - left + 1, 0);
    }
};

23-01 分割回文串 II

func minCut(s string) int {
    n:=len(s)
    isPalidrom:=make([][]int,n)
    for i:=0;i<n;i++ {
        isPalidrom[i]=make([]int,n)
    }
    for i:=0;i<n;i++{
        for j:=0;i-j>=0&&i+j<n&&s[i-j]==s[i+j];j++ {
            isPalidrom[i-j][i+j]=1
        }
        for j:=0;i-j>=0&&i+j+1<n&&s[i-j]==s[i+j+1];j++{
            isPalidrom[i-j][i+j+1]=1
        }
    }
    dp:=make([]int,n+1)
    for i:=0;i<=n;i++ {
        dp[i]=i
        for j:=0;j<i;j++ {
            if isPalidrom[j][i-1]==1 && dp[j]+1<dp[i] {
                dp[i]=dp[j]+1
            }
        }
    }
    return dp[n]-1
}

24-01 旋转链表

func rotateRight(head *ListNode, k int) *ListNode {
    if k == 0 || head == nil || head.Next == nil {
        return head
    }
    n := 1
    iter := head
    for iter.Next != nil {
        iter = iter.Next
        n++
    }
    m := n - k % n
    if m == n {
        return head
    }
    iter.Next = head
    for m > 0 {
        iter = iter.Next
        m--
    }
    ret := iter.Next
    iter.Next = nil
    return ret
}

25-01 第一个错误的版本

func firstBadVersion(n int) int {
    return sort.Search(n, func(i int) bool { return isBadVersion(i) })
}

26-01 只出现一次的数字

class Solution(object):
    def singleNumber(self, nums):
        return reduce(operator.xor, nums)

27-01 构建乘积数组

func constructArr(a []int) []int {
    n := len(a)
    ans := make([]int, n)
    if n == 0 {
        return ans
    }
    ans[0] = 1
    for i := 1; i < n; i++ {
        ans[i] = ans[i-1] * a[i-1]
    }
    for i, r := n-1, 1; i>=0; i-- {
        ans[i] = ans[i] * r;
        r = r * a[i]
    }
    return ans
}

28-01 无重叠区间

func eraseOverlapIntervals(intervals [][]int) int {
    sort.Slice(intervals, func(i, j int) bool { return intervals[i][1] < intervals[j][1] })
    ans, ri := 0, intervals[0][1]
    for _, in := range intervals[1:] {
        if in[0] < ri {
            ans++
        } else {
            ri = in[1]
        }
    }
    return ans
}

29-01 原子的数量

class Solution {
private:
    int i;

    unordered_map<string, int> dfs(const string &formula) {
        int &i_ = i;
        unordered_map<string, int> ans;
        while (i < formula.size()) {
            if (formula[i] == '(') {
                ++i;
                auto sub = dfs(formula);
                if (isdigit(formula[i])) {
                    auto pos = formula.find_first_not_of("0123456789", i);
                    int mul = stoi(formula.substr(i, pos - i));
                    for (auto&[k, v]:sub) ans[k] += mul * v;
                    i = pos;
                } else {
                    for (auto&[k, v]:sub) ans[k] += v;
                }
            } else if (formula[i] == ')') {
                ++i;
                break;
            } else {
                int j = find_if(formula.begin() + i + 1, formula.end(), [](char c) { return !islower(c); })
                        - formula.begin();
                string key = formula.substr(i, j - i);
                if (j >= formula.size() || !isdigit(formula[j])) {
                    ans[key] += 1;
                    i = j;
                } else {
                    int k = find_if(formula.begin() + j + 1, formula.end(),
                                    [](char c) { return !isdigit(c) || c == ')'; }) - formula.begin();
                    int val = stoi(formula.substr(j, k - j));
                    ans[key] += val;
                    i = k;
                }
            }
        }
        return ans;
    }

public:
    string countOfAtoms(const string &formula) {
        auto ans = dfs(formula);
        vector<tuple<string, int>> result;
        for (auto&[k, v]:ans) result.emplace_back(k, v);
        sort(result.begin(), result.end());
        string ret;
        for (auto&[k, v]:result) {
            ret += v == 1 ? k : k + to_string(v);
        }
        return ret;
    }
};

30-01 交错字符串

class Solution {
private:
    bool dp[101][101];
    int n1, n2, n3;
public:
    bool isInterleave(const string &s1, const string &s2, const string &s3) {
        n1 = s1.size(), n2 = s2.size(), n3 = s3.size();
        if (n1 + n2 != n3) return false;
        for (int i = 0; i <= s1.size(); ++i) {
            for (int j = 0; j <= s2.size(); ++j) {
                dp[i][j] = (i == 0 && j == 0) ||
                           (i > 0 && dp[i - 1][j] && s1[i - 1] == s3[i + j - 1]) ||
                           (j > 0 && dp[i][j - 1] && s2[j - 1] == s3[i + j - 1]);
            }
        }
        return dp[n1][n2];
    }
};

31-01 环形链表

func hasCycle(head *ListNode) bool {
    if head == nil || head.Next == nil {
        return false
    }
    slow, fast := head, head.Next
    for fast != slow {
        if fast == nil || fast.Next == nil {
            return false
        }
        slow = slow.Next
        fast = fast.Next.Next
    }
    return true
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值