1. 程式人生 > 其它 >2022.01.25刷題

2022.01.25刷題

121. 買賣股票的最佳時機 todo


415. 字串相加

感覺邏輯很不清晰...

//我的
string addStrings(string num1, string num2) {
    reverse(num1.begin(), num1.end());        
    reverse(num2.begin(), num2.end());        
    if(num1.size()<num2.size())swap(num1,num2);
    int tmp = 0;
    int n = num1.size(), m = num2.size();
    for(int i = 0; i< m || tmp;i++){ //這直接是字串模式的大數加法是吧.. 普通的好像挺簡單的.
        if(i==n) num1+='0'; //不夠了補0
        num1[i] += tmp; //
        if(i<m) num1[i] += num2[i] -'0';
        tmp = 0;
        if(num1[i]>'9'){
            num1[i]-=10;
            tmp = 1;
        }
    } 
    reverse(num1.begin(), num1.end());        
    return num1;
}

169. 多數元素

簡單題 可是題解有好多, 我只用了um做.


350. 兩個陣列的交集 II

便捷的交換方向..

vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        if (nums1.size() > nums2.size()) {
            return intersect(nums2, nums1);
        }
}

正解:小的進um, 大的命中直接 --;

vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
    if(nums1.size()>nums2.size())return intersect(nums2, nums1);
    unordered_map<int,int> um;
    for(auto i:nums1) um[i]++;
    vector<int> res;
    for(auto i:nums2){
        if(um.count(i)) {
            res.push_back(i),um[i]--;
            if(um[i]==0) um.erase(i);
        }
    } 
    return res;
}

我的

vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
    unordered_map<int,int> um1,um2;
    for(auto i:nums1) um1[i]++; 
    for(auto i:nums2) um2[i]++;
    vector<int> res;
    for(auto i:um1){
        int cnt = min(i.second, um2[i.first]);
        while(cnt--) res.push_back(i.first);
    }
    return res;
}

434. 字串中的單詞數

int countSegments(string s) {
    int ans = 0;
    s += ' '; //方便分解單詞.
    for (int i = 1; i < s.size(); i++) 
        if (s[i] == ' ' && s[i - 1] != ' ') ans++; //如果有的話.
    return ans;
}

387. 字串中的第一個唯一字元

簡單解法: O(2n)

高效一點: 雜湊表直接存索引 O(n+26)

int firstUniqChar(string s) {
    vector<int> um(26);
    int res = INT_MAX;
    for(int i =0;i<s.size();i++){
        if(!um[s[i]-'a']) um[s[i]-'a'] = i+1;
        else um[s[i]-'a'] = -1;
    }
    for(auto i:um){
        if(i>0) res=min(res,i);
    }
    return res==INT_MAX?-1:res-1;
}

155. 最小棧

//兩個數的棧.
stack<int> s;
stack<int> smin;
MinStack() {
    smin.push(INT_MAX); //輸入max可以方便底下的min比較.
}

void push(int val) {
    s.push(val);
    smin.push(min(val,smin.top()));
}

void pop() {
    s.pop();smin.pop();
}

int top() {
    return s.top();
}

int getMin() {
    return smin.top();
}
//原始解法, 相當於三個數的棧.
stack<int> s1;
stack<pair<int,int>> s2;
int minval = 0,mincnt = 0;
MinStack() {}

void push(int val) {
    if(!s2.empty()) minval=s2.top().first,mincnt=s2.top().second;
    if(s1.size()==0 || minval >val) minval = val,mincnt = 1;
    else if(minval == val) mincnt++;
    s1.push(val);
    s2.push({minval,mincnt});
}

void pop() {
    s1.pop();
    s2.pop();
}

int top() {
    return s1.top();
}

int getMin() {
    return s2.top().first;
}

453. 最小操作次數使陣列元素相等

其實每次n-1個元素+1 就是最大的元素-1;

int minMoves(vector<int>& a) {
    int min = *min_element(a.begin(),a.end());
    int res = 0; 
    for(auto i:a) res+=i-min;
    return res;
}

733. 影象渲染

BFS的框架.

vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) {
    vector<vector<int>> dir={{1,0},{-1,0},{0,1},{0,-1}};
    queue<pair<int,int>> s;
    int n = image.size(), m = image[0].size();
    s.push({sr,sc});
    int origin = image[sr][sc];
    if(color==origin) return image; //注意... 非常重要.
    while(!s.empty()){
        image[s.front().first][s.front().second] = color; 
        for(auto i:dir){
            auto x = s.front().first + i[0],y = s.front().second + i[1];
            if(x>=0 && x<n && y>=0 && y<m && image[x][y] == origin){
                s.push({x,y});
            }
        }
        s.pop();
    }
    return image;
}

234. 迴文連結串列

如何O(n) , O(1) 也不簡單..

bool isPalindrome(ListNode* head) {
    if(!head->next) return true; //單一節點, 對.
    ListNode* slow = head, *fast = head;
    while(fast->next && fast->next->next){
        fast = fast->next->next;
        slow = slow->next;
    }
    ListNode* hh = slow->next;
    slow->next = NULL;
    ListNode* newhead = NULL;
    while(hh){ //反轉連結串列.
        auto oldNext = hh->next;
        hh->next = newhead;
        newhead = hh;
        hh = oldNext;
    }
    while(newhead){  //需要注意 後半段是一定比前半段短...
        if(head->val!=newhead->val) return false;
        head = head->next, newhead = newhead->next;
    } 
    return true;
}

705. 設計雜湊集合

瞭解下如何使用 bitset

class MyHashSet {
public:
    bitset<1000005> hashSet;
    MyHashSet() {  } 
    void add(int key) {
        hashSet[key] = 1;
    }
    void remove(int key) {
        hashSet[key] = 0;
    } 
    bool contains(int key) {
        return hashSet.test(key);
    }
};

414. 第三大的數

使用有序集合, 如果大於最小的就抹去最小的.

int thirdMax(vector<int>& nums) {
    set<int> s;
    for(auto i:nums){
        if(s.count(i))continue;
        s.insert(i);
        if(s.size()>3) s.erase(s.begin());
    }
    return s.size()==3?*s.begin():*s.rbegin(); //注意是 rbegin()是返回最大的.
}
// 原本 模擬法 容易出錯.
int thirdMax(vector<int>& nums) {
    long long a=LONG_MIN,b=LONG_MIN,c=LONG_MIN;
    for(auto i:nums){
        if(i==b||i==a)continue;;
        if(i>c) {
            c = i;
            if(c>b){
                swap(c,b); 
                if(b>a)
                    swap(a,b);
            } 
        }
    }
    return c!=LONG_MIN?c:a;
}

326. 3 的冪

其實可以直接判斷是否是最大的約數..

bool isPowerOfThree(int n) {
    while(n && n%3==0){
        n/=3;
    }
    return n == 1;
}
// O(1)
bool isPowerOfThree(int n) {
    return n > 0 && 1162261467 % n == 0;
}
//我的
bool isPowerOfThree(int n) {
    if(n<=0) return false;
    n = abs(n);
    while(n>1){
        if(n%3) return false;
        n/=3;
    }       
    return true;;
}

506. 相對名次

vector<string> findRelativeRanks(vector<int>& score) {
    int n = score.size();
    vector<string> gold = {"Gold Medal","Silver Medal","Bronze Medal"};
    vector<pair<int,int>> arr;
    for(int i = 0;i<n; i++){
        arr.emplace_back(make_pair(-score[i],i));
    } // 這樣子直接放一起排序, 可以保持原有的序號, 知道哪個下標排第幾. 
      // emplace_back 和 make_pair好像可以加快速度?
    sort(arr.begin(),arr.end());
    vector<string> ans(n);
    for(int i = 0;i<n;i++){
        ans[arr[i].second] = i>2?to_string(i+1):gold[i];
    }
    return ans;
}

// 原始.

vector<string> findRelativeRanks(vector<int>& score) {
    int n = score.size();
    vector<int> origin = score;
    sort(score.begin(), score.end());
    unordered_map<int, string> um;
    vector<string> gold = {"","Gold Medal","Silver Medal","Bronze Medal"};
    vector<string> res;
    for(int i = 0; i < n;i++){
        um[score[i]] = n-i<=3?gold[n-i]:to_string(n-i);
    }
    for(auto i:origin){
        res.push_back(um[i]);
    }
    return res;
}

劍指 Offer 11. 旋轉陣列的最小數字 //todo

這題意思是對旋轉陣列做二分..


劍指 Offer 42. 連續子陣列的最大和

腦筋急轉彎, 還有分治的做法. 其實就是如果前一個數最大小於0 就不要他了.

int maxSubArray(vector<int>& nums) {
    int pre = 0, maxAns = nums[0];
    for (const auto &x: nums) {
        pre = max(pre + x, x);
        maxAns = max(maxAns, pre);
    }
    return maxAns;
}

劍指 Offer 10- I. 斐波那契數列\todo

矩陣快速冪的方法.

面試題 10.01. 合併排序的陣列

雙指標題目, 歸併排序的模板.

void merge(vector<int>& A, int m, vector<int>& B, int n) {
    int a = m - 1, b= n - 1;
    for(int i = a+b+1;i>=0 ;i--){
        if(a<0||b<0) A[i]=a>=0?A[a--]:B[b--];
        else if(A[a] >= B[b]) A[i] = A[a--];
        else A[i] = B[b--];
    }
}

258. 各位相加\todo

有O(1)的解法.

290. 單詞規律

    bool wordPattern(string pattern, string s) {
        unordered_map<char,string> um;
        unordered_map<string,char> um2;
        int l = 0, len = 0;
        for(int i = 0;i<pattern.size();i++){
            while(l+len<s.size()&&s[l+len]!=' ') len++;
            if(l>s.size()) return false;
            string ss = s.substr(l,len); 
            char c = pattern[i];
            //---------------------
            if(um.count(c)^um2.count(ss)) return false;
            if(um.count(c)){
                if(um[c]!=ss || um2[ss]!=c) return false;
            }
            else um[c] = ss, um2[ss] = c;
            //--------------------------上面的改成下面好一點...
            if (str2ch.count(tmp) && str2ch[tmp] != ch) return false;
            if (ch2str.count(ch) && ch2str[ch] != tmp) return false;
            str2ch[tmp] = ch; ch2str[ch] = tmp;
            //------------------------
            l = l+len+1, len = 0;
        } 
        return l>=s.size();
    }

605. 種花問題

有個跳格子解法, 可是不知道其他地方能用到不.

448. 找到所有陣列中消失的數字

有個O(1)的原地操作解法

405. 數字轉換為十六進位制數

補碼是 原碼取反再加一.

string toHex(int num) {
    if(num == 0) return "0"; // 避免出現先導0
    string res = "";
    for(int i = 7;i>=0;i--){
        int c = (num>>(4*i)) & 0xf; //這裡記住是左移 4 * i 位.
        if(res.size()>0 || c!=0){
            res+= c<=9?'0'+c:'a'+c-10; // 這裡是
        }
        // cout<<c<<' ';
    } 
    return res;
}