zoukankan      html  css  js  c++  java
  • 力扣部分刷题记录

    1. 两数之和

    思路:

    暴力遍历
    

    代码:

    class Solution {
    public:
        vector<int> twoSum(vector<int>& nums, int target) {
            
            int lenNums = nums.size();
            int a, b;
            for(int i = 0; i < lenNums; i ++){
                for(int j = i + 1; j < lenNums; j ++){
                    if(nums[i] + nums[j] == target){
                        vector<int> res;
                        res.push_back(i);
                        res.push_back(j);
                        return res;
                    }
                }
            }
        vector<int> res;
        return res;
        }
        
    };
    

    2. 两数相加

    思路:

    遍历链表
    

    代码:

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            ListNode * res = new ListNode();
            ListNode * h = res;
            int c = 0;
            while(l1 || l2){
                int x = 0;
                if(l1) x += l1->val;
                if(l2) x += l2->val;
                x += c;
                //cout << " x= " << x << endl;
                h->next = new ListNode(x % 10);
                c = x / 10;
                h = h->next;
                if(l1) l1 = l1->next;
                if(l2) l2 = l2->next;
            }
            if(c){
                h->next = new ListNode(1);
            }
            return res->next;
        }
    };
    

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

    思路:

    暴力:
        枚举每一个字符,当做当前子串的头,依次遍历下去,直到不合格。
    那么显然是要超时的,在暴力的基础做一个小优化即可:
        当我们枚举s[i]为头部的时候,遍历到s[j]发现,s[j]在[i, j]之间出现过,我们用一个map来记录字符最新的位置,那么显然在 [m[s[j]] + 1, j]这之中是没有重复字符出现的,利用这个技巧可以在线性时间内解决。
    

    代码:

    class Solution {
    public:
        int lengthOfLongestSubstring(string s) {
    
            int res = 0, cur = 0, idx = 0;
            int lenS = s.size();
            map<char, int> mp;
            for(int i = 0; i < lenS; i ++){
                if(mp[s[i]] && mp[s[i]] > idx){
                    res = max(res, cur);
                    cur = i - mp[s[i]] + 1;
                    idx = mp[s[i]];
                    mp[s[i]] = i + 1;
                } else{
                    mp[s[i]] = i + 1;
                    cur ++;
                }
            }
            return max(res, cur);
    
        }
    };
    

    4. 寻找两个正序数组的中位数

    思路:

    二分。
    分奇偶来讨论,每次寻找两个数组中第(k / 2 - 1) 个元素,很明显小的那个不符合要求,所以他前面的包括他都可以删去,用指针来实现。特判特殊情况即可。
    

    代码:

    class Solution {
    public:
    
        int find(vector<int> a, vector<int> b, int k){
            int la = a.size();
            int lb = b.size();
            int idxA = 0, idxB = 0;
            while(1){
                if(idxA == la) return b[idxB + k - 1];
                if(idxB == lb) return a[idxA + k - 1];
                if(k == 1) return min(a[idxA], b[idxB]);
                
                int newIdxA = min(idxA + k / 2 - 1, la - 1);
                int newIdxB = min(idxB + k / 2 - 1, lb - 1);
                
                if(a[newIdxA] <= b[newIdxB]){
                    k -= newIdxA - idxA + 1;
                    idxA = newIdxA + 1;
                } else{
                    k -= newIdxB - idxB + 1;
                    idxB = newIdxB + 1;
                }
    
            }
        }
    
        double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
            
            int all = nums1.size() + nums2.size();
            double res;
            if(all & 1) res = find(nums1, nums2, all / 2 + 1);
            else res = (find(nums1, nums2, all / 2) + find(nums1, nums2, all / 2 + 1)) / 2.0;
            return res;
    
        }
    };
    

    5. 最长回文子串

    思路:

    用Manacher算法求出最长回文串的长度和其中心的下标即可。
    

    代码:

    class Solution {
    public:
        
        pair<int, int> Manacher(char * s, int len){
            int p[2010];
            int maxLen = 0, maxId;
            int mx = 0, id = 1;
            for(int i = 1; i <= len; i ++){
                if(mx > i) p[i] = min(p[2 * id - i], mx - i);
                else p[i] = 1;
                while(i + p[i] <= len && s[i + p[i]] == s[i - p[i]]) p[i] ++;
                if(p[i] >= mx) { mx = p[i]; id = i; }
                if(maxLen < p[i] - 1){
                    maxLen = p[i] - 1;
                    maxId  = i;
                }
            }
            return {maxLen, maxId};
        }
        
        string longestPalindrome(string s) {
            char str[2010];
            int lenStr = 0;
            for(int i = 0; i < s.size(); i ++){
                str[ ++ lenStr] = '~';
                str[ ++ lenStr] = s[i];
            }
            str[ ++ lenStr] = '~';
            pair<int, int> ans = Manacher(str, lenStr);
            int a = ans.first;
            int b = ans.second;
            cout << a << " " << b << endl;
            string res = "";
            for(int i = b - a + 1; i < b + a; i ++){
                if(str[i] == '~') continue;
                res += str[i];
            }
            return res;
        }
    };
    

    6. Z 字形变换

    思路:

    找规律。
    设 m = 2 * numRows - 2;
    那么遍历去 % m 很容易发现规律
    

    代码:

    class Solution {
    public:
        string convert(string s, int numRows) {
            if(numRows == 1) return s;
            int len = s.size();
            vector<string> tmp(numRows);
            string res = "";
            int m = 2 * numRows - 2;
            for(int i = 0; i < len; i ++){
                int t = i % m;
                if(t < numRows) tmp[t].push_back(s[i]);
                else tmp[m - t].push_back(s[i]);
            }
            for(int i = 0; i < tmp.size(); i ++)
                res += tmp[i];
            return res;
        }
    };
    

    7. 整数反转

    思路:

    注意溢出
    

    代码:

    class Solution {
    public:
        int reverse(int x) {
            
            long long res = 0;
            long long mx  = (1ll << 31) - 1;
            long long mn  = - (1ll << 31);
            int mark = 0;
            if(x < 0){
                mark = 1;
                if(x == mn) x = 0;
                else x *= -1;
            }
            while(x){
                res = res * 10 + x % 10;
                x /= 10;
            }
            if(mark) res *= -1;
            if(res > mx || res < mn) res = 0;
            return int(res);
        }
    };
    

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

    思路:

    模拟即可
    

    代码:

    class Solution {
    public:
        int myAtoi(string str) {
            int lenStr = str.size();
            string s = "";
            int symbol = 0; // 记录符号
            int flag = 0;
            for(int i = 0; i < lenStr; i ++){
                if(!flag && str[i] == ' ') continue;
                else{
                    if(str[i] >= '0' && str[i] <= '9')
                        s += str[i];
                    else if(!flag && str[i] == '-')
                        symbol = -1;
                    else if(!flag && str[i] == '+')
                        symbol = 1;
                    else break;
                    flag = 1;
                }
            }
            if(s.empty()) return 0;
            long long num = 0;
            for(int i = 0; i < s.size(); i ++) {
                num = num * 10 + (s[i] - '0');
                if(num > INT_MAX) break;
            }
            if(symbol == -1) num *= -1;
            if(num > INT_MAX) num = INT_MAX;
            if(num < INT_MIN) num = INT_MIN;
            return int(num);
            return 0;
        }
    };
    

    9. 回文数

    思路:

    暴力
    

    代码:

    class Solution {
    public:
        bool isPalindrome(int x) {
            if(x < 0) return false;
            long long y = 0;
            int tmp = x;
            while(x){
                y = y * 10 + x % 10;
                x /= 10;
            }
            return y == tmp;
        }
    };
    

    10. 正则表达式匹配

    思路:

    二维DP
    设f[i][j]: s中前i个字符与p中前j个字符是否合法匹配
        1. p[j] = '*':
        	f[i][j] |= f[i][j - 2]	// 将j-1删去
        	if(p[j - 1] == s[i]) f[i][j] |= f[i - 1][j]
        2. p[j] != '*':
    		if(p[j] == '.' || p[j] == s[i]) f[i][j] |= f[i - 1][j - 1]
    return f[size(s)][size(p)]
    

    代码:

    class Solution {
    public:
        bool isMatch(string s, string p) {
            int ls = s.size();
            int lp = p.size();
            auto check = [&](int i, int j){
                if(i == 0) return false;
                if(p[j - 1] == '.' || p[j - 1] == s[i - 1]) return true;
                return false;
            };
            
            int f[ls + 10][lp + 10];
            memset(f, 0, sizeof f);
            f[0][0] = true;
            for(int i = 0; i <= ls; i ++)
                for(int j = 1; j <= lp; j ++){
                    if(p[j - 1] == '*'){
                        if(j >= 2) f[i][j] |= f[i][j - 2];
                        if(check(i, j - 1)) f[i][j] |= f[i - 1][j];
                    } else{
                        if(check(i, j)) f[i][j] |= f[i - 1][j - 1];
                    }
                }
            return f[ls][lp];
        }
    };
    

    11. 盛最多水的容器

    思路:

    双指针
    很显然的一个事实是:高度取决于短的板子
    我们可以逐渐缩小宽度来获得更高的高度
        
    // 当h[i] < h[j]时,i++, 那么高度是有可能变大的,如果是j--,那么高度只可能更小,并且由于宽度还变小了,那么j--一定不会是最优解。
    if h[i] < h[j]:
        i ++;
    else j --;
    

    代码:

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

    12. 整数转罗马数字

    思路:

    把罗马字符可以代表的字符都手动预处理下来,共计13项,然后从大到小遍历即可。
    

    代码:

     string rome[] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
    
    int val[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
    
    class Solution {
    public:
        
       
        
        string intToRoman(int num) {
            string res = "";
            for(int i = 0; i < 13; i ++){
                while(num >= val[i]){
                    res += rome[i];
                    num -= val[i];
                }
            }
            return res;
        }
    };
    

    13. 罗马数字转整数

    思路:

    用hash映射出罗马字母对应的数,然后从左往右遍历一遍,如果当前值小于左边就减,反之就加。(注意处理边界)
    

    代码:

    class Solution {
    public:
        int romanToInt(string s) {
            map<char, int> mp;
            mp['I'] = 1;
            mp['V'] = 5;
            mp['X'] = 10;
            mp['L'] = 50;
            mp['C'] = 100;
            mp['D'] = 500;
            mp['M'] = 1000;
            
            int n = s.length();
            int res = 0;
            for(int i = 0; i < n - 1; i ++){
                if(mp[s[i]] >= mp[s[i + 1]])
                    res += mp[s[i]];
                else res -= mp[s[i]];
            }
            res += mp[s[n - 1]];
            return res;
        }
    };
    

    14. 最长公共前缀

    思路:

    暴力
    

    代码:

    class Solution {
    public:
        
        int min(int a, int b){
            return a <= b ? a : b;
        }
        
        string longestCommonPrefix(vector<string>& strs) {
            string res = "";
            int n = strs.size();
            if(n == 0) return "";
            int mn = 1e9;
            for(int i = 0; i < n; i ++) mn = min(mn, strs[i].size());
            for(int i = 0; i < mn; i ++){
                char c = strs[0][i];
                int mark = 1;
                for(int j = 1; j < n; j ++)
                    if(strs[j][i] != c){
                        mark = 0;
                        break;
                    }
                if(mark) res += c;
                else break;
            }
            return res;
        }
    };
    

    51. N 皇后

    思路:

    dfs枚举
    

    代码:

    class Solution {
    public:
        
        bool check(int i, int pos[]){
            for(int j = 1; j < i; j ++)
                if(pos[i] == pos[j] || abs(i - j) == abs(pos[i] - pos[j])) return false;
            return true;
        }
        
        vector<string> record(int pos[], int n){
            vector<string> res;
            for(int i = 1; i <= n; i ++){
                string tmp = "";
                for(int j = 1; j <= n; j ++)
                    if(pos[i] == j) tmp += 'Q';
                    else tmp += '.';
                res.push_back(tmp);
            }
            return res;
        }
        
        void queen(int i, int *pos, int n, vector<vector<string>> & res){
            if(i > n) res.push_back(record(pos, n));
            else{
                for(int j = i; j <= n; j ++){
                    swap(pos[i], pos[j]);
                    if(check(i, pos)) queen(i + 1, pos, n, res);
                    swap(pos[i], pos[j]);
                }
            }
        }
        
        vector<vector<string>> solveNQueens(int n) {
            vector<vector<string>> res;
            int pos[n + 1];
            for(int i = 1; i <= n; i ++) pos[i] = i;
            queen(1, pos, n  res);
            return res;
        }
    };
    

    216. 组合总和 III

    思路:

    dfs 暴力枚举
    

    代码:

    class Solution {
    public:
        
        vector<vector<int>> res;
        int a, b;
        void dfs (int sum, int num, int cnt, vector<int> vec){
            if(cnt == a && sum == b){
                res.push_back(vec);
                return;
            }
            if(num > 9 || sum > b || cnt > a) return;
            for(int i = num; i <= 9; i ++){
                vec.push_back(i);
                dfs(sum + i, i + 1, cnt + 1, vec);
                vec.pop_back();
            }
        }
        
        
        vector<vector<int>> combinationSum3(int k, int n) {
            
            
            a = k, b = n;
            
            vector<int> vec;
            dfs(0, 1, 0, vec);
            return res;
            
        }
    };
    
  • 相关阅读:
    java 并发性和多线程 -- 读感 (一 线程的基本概念部分)
    [翻译]Spring框架参考文档(V4.3.3)-第二章Spring框架介绍 2.1 2.2 翻译--2.3待继续
    java 内存模型
    控制反转容器& 依赖注入模式 ---读感。
    go json null字段的转换
    分布式数据库----数据同步
    java 多线程--- Thread Runnable Executors
    go runtime.Gosched() 和 time.Sleep() 做协程切换
    sql 里面 join in 的差别,join的用法
    定时器
  • 原文地址:https://www.cnblogs.com/nonameless/p/13718851.html
Copyright © 2011-2022 走看看