12. 數(shù)學(xué)


1. 位運(yùn)算
2. 10進(jìn)制進(jìn)位,取余
3. 找規(guī)律題目

136. Single Number
Given an array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
利用取余操作的特性相同為0,不同為1。可以得出,只出現(xiàn)一次的數(shù)字。
int singleNumber(vector<int>& nums) {
    int start = 0;
    for (auto n:nums) {
        start ^= n;
    }
    return start;
}

137. Single Number II
Given an array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
136的升級(jí)版,可以使用32bit保存對(duì)應(yīng)每個(gè)bit之和取余進(jìn)行操作。對(duì)重復(fù)出現(xiàn)的那個(gè)的值進(jìn)行取余,如本題中的3,上題中的2。
int singleNumber(vector<int>& nums) {
    vector<int> table(32, 0);
    int res = 0;
    
    for (int i = 0; i < 32; ++i) {
        for (auto j = 0; j < nums.size(); ++j) {
            table[i] += ((nums[j] >> i)&1);
            table[i] %= 3;
        }
        res |= (table[i] << i);
    }
    return res;
}

29. Divide Two Integers
Divide two integers without using multiplication, division and mod operator.

If it is overflow, return MAX_INT.
  • 使用位運(yùn)算實(shí)現(xiàn)除法
  • 主要思想是倍數(shù)可以用2的指數(shù)和求出
int divide(int dividend, int divisor) {
    if (!divisor || (dividend == INT_MIN && divisor == -1)) {
        return INT_MAX;
    }
    
    int sign = ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0) ) ? -1 : 1;
    long long dvd = labs(dividend);
    long long dvs = labs(divisor);
    int res = 0;
    
    while (dvs <= dvd) {
        long long count = 1, dv = dvs;
        while ((dv << 1) <= dvd) {
            dv <<= 1;
            count <<= 1;
        }
        dvd -= dv;
        res += count;
    }
    return res*sign;
}

50. Pow(x, n)
https://leetcode.com/problems/powx-n
Implement pow(x, n).
不適用位運(yùn)算時(shí)間復(fù)雜度為O(n),使用位運(yùn)算時(shí)間復(fù)雜度為O(logn)
使用位運(yùn)算的關(guān)鍵是理解將某個(gè)數(shù)值拆分成二進(jìn)制表示的形式,如 9的二進(jìn)制表示為 1001 即是 2^3 + 2^0
double myPow(double x, int n) {
    long long p = labs(n);
    double res = 1;
    while (p > 0) {
        if (p & 1) res *= x;
        x *= x;
        p >>= 1;
    }
    return n < 0 ? 1/res : res;
}

9. Palindrome Number
https://leetcode.com/problems/palindrome-number/
Determine whether an integer is a palindrome. Do this without extra space.
巧妙地利用sum記錄一般數(shù)目,只能在原地進(jìn)行運(yùn)算。其實(shí)也是移位,不過(guò)是10進(jìn)制的。遍歷次數(shù)降低一半且空間復(fù)雜度為O(1)
bool isPalindrome(int x) {
    if (x < 0 || (x != 0 && x % 10 == 0)) return false;
    int sum = 0;
    while (x > sum) {
        sum = sum*10 + x%10;
        x /= 10;
    }
    
    return (x == sum) || (x == sum/10);
}

8. String to Integer (atoi)
https://leetcode.com/problems/string-to-integer-atoi/
Implement atoi to convert a string to an integer.

Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.

Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.

Update (2015-02-10):
The signature of the C++ function had been updated. If you still see your function signature accepts a const char * argument, please click the reload button  to reset your code definition.
實(shí)現(xiàn)atoi函數(shù),需要注意的是 1. 去掉前面和后面的空白字符 2. 有效字符必須在'0'和'9'之間 3. 大于INT_MAX的輸出INT_MAX,小于INT_MIN的 INT_MIN
int myAtoi(string str) {
    int cur = str.find_first_not_of(' ');
    int pos = 1;
    if (str[cur] == '-' || str[cur] == '+') {
        pos = (str[cur] == '-') ? -1 : 1;
        cur++;
    }
    
    long result = 0;
    while (cur < str.size() && str[cur] >= '0' && str[cur] <= '9') {
        result = result*10 + str[cur++] - '0';
        if (result*pos >= INT_MAX) return INT_MAX;
        if (result*pos <= INT_MIN) return INT_MIN;
    }
    return result*pos;
}

31. Next Permutation
https://leetcode.com/problems/next-permutation/
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place, do not allocate extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
解析: 數(shù)組的下一個(gè)字典順序
邊界:數(shù)組大小小于2
思路:找規(guī)律的題目,1. 從后往前找第一個(gè)相鄰的構(gòu)成升序的p[n] < p[n+1],n點(diǎn)為違法點(diǎn)。2. 對(duì)p[n]之后的元素進(jìn)行逆序 3. 在排序后的p[n+1]至最后的第一個(gè)大于p[n]的元素與p[n]交換
C++ STL中下一個(gè)字典順序的函數(shù),next_permutation(beg, end)
時(shí)間復(fù)雜度:O(n)
void nextPermutation(vector<int>& nums) {
    if(nums.size() < 2) return;
    int i = nums.size() - 2;
    for (;i >= 0; --i) {
        if (nums[i] < nums[i+1]) break;
    }
    reverse(nums.begin() + i + 1, nums.end());
    if (i == -1) return;
    int j = i+1;
    for (; j < nums.size(); ++j) {
        if (nums[i] < nums[j]) {
            swap(nums[i], nums[j]);
            break;
        }
    }
}

60. Permutation Sequence
https://leetcode.com/problems/permutation-sequence/
The set [1,2,3,…,n] contains a total of n! unique permutations.

By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):

"123"
"132"
"213"
"231"
"312"
"321"
Given n and k, return the kth permutation sequence.

Note: Given n will be between 1 and 9 inclusive.
求[1,n]構(gòu)成的第k個(gè)數(shù)列,可以使用31題中的方法一步一步來(lái),也可以根據(jù)規(guī)律去做。規(guī)律如下:第一位為每(n-1)!為1組,則res[0]為nums[k/(n-1)!]。剩下的n-1個(gè)數(shù)組也是這個(gè)規(guī)律。每次需要更新k和count,k %= count(含義為該組中第k個(gè))。
string getPermutation(int n, int k) {
    vector<int> nums(n);
    int count = 1;
    for (int i = 0; i < n; ++i) {
        nums[i] = i + 1;
        count *= (i+1);
    }
    
    k--;
    string res;
    for (int i = 0; i < n; ++i) {
        count /= (n - i);
        int cur = k/count;
        res += ('0' + nums[cur]);
        
        k %= count;
        for(int j = cur; j < n - i - 1; ++j) {
            nums[j] = nums[j + 1];
        }
    }
    return res;
}

13. Roman to Integer
https://leetcode.com/problems/roman-to-integer/
Given a roman numeral, convert it to an integer.

Input is guaranteed to be within the range from 1 to 3999.
羅馬數(shù)字轉(zhuǎn)換成阿拉伯?dāng)?shù)字,主要是找出每個(gè)羅馬數(shù)字對(duì)應(yīng)的大小
int romanToInt(string s) {
    unordered_map<char,int> hash_table = {{'I',1}, {'V',5}, {'X', 10}, {'L', 50}, {'C', 100}, {'D', 500}, {'M', 1000}};
    int sum = hash_table[s.back()];
    for (int i = s.size() - 2; i >= 0; --i) {
        if (hash_table[s[i]] < hash_table[s[i+1]]) {
            sum -= hash_table[s[i]];
        } else {
            sum += hash_table[s[i]];
        }
    }
    
    return sum;
}

59. Spiral Matrix II
Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.

For example,
Given n = 3,

You should return the following matrix:
[
 [ 1, 2, 3 ],
 [ 8, 9, 4 ],
 [ 7, 6, 5 ]
]
找出規(guī)律?。?!實(shí)現(xiàn)要細(xì)心
vector<vector<int>> generateMatrix(int n) {
    vector<vector<int>> vv(n,vector<int>(n,0));
    int rowStart = 0, rowEnd = n - 1;
    int colStart = 0, colEnd = n - 1;
    int cnt = 1;
    
    while (rowStart <= rowEnd && colStart <= colEnd) {
        for(int i = colStart; i<= colEnd; i++)
            vv[rowStart][i] = cnt++;
        rowStart++;
    
        for(int i = rowStart; i<= rowEnd; i++)
            vv[i][colEnd] = cnt++;
        colEnd--;
        
        for (int i = colEnd; i >= colStart; --i) {
            vv[rowEnd][i] = cnt++;
        }
        rowEnd--;
        
        for (int i = rowEnd; i >= rowStart; --i) {
            vv[i][colStart] = cnt++;
        }
        colStart++;
    }
    return vv;
}

48. Rotate Image
https://leetcode.com/problems/rotate-image/
You are given an n x n 2D matrix representing an image.

Rotate the image by 90 degrees (clockwise).

Follow up:
Could you do this in-place?
將數(shù)組旋轉(zhuǎn)2次,一次是水平或垂直,一次是斜著沿著軸。順序無(wú)關(guān)
/*
 * clockwise rotate
 * first reverse up to down, then swap the symmetry 
 * 1 2 3     7 8 9     7 4 1
 * 4 5 6  => 4 5 6  => 8 5 2
 * 7 8 9     1 2 3     9 6 3
*/
void rotate(vector<vector<int> > &matrix) {
    reverse(matrix.begin(), matrix.end());
    for (int i = 0; i < matrix.size(); ++i) {
        for (int j = i + 1; j < matrix[i].size(); ++j)
            swap(matrix[i][j], matrix[j][i]);
    }
}

149. Max Points on a Line
https://leetcode.com/problems/max-points-on-a-line/
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
找出一條直線(xiàn)上最多的點(diǎn)
這種題最怕的就是直接被嚇到,沒(méi)思路。其實(shí)一步步挨個(gè)遍歷,下層循環(huán)遍歷剩余點(diǎn)即可。頂層循環(huán)下,當(dāng)前點(diǎn)做起點(diǎn),建立最大公約數(shù)的map,記錄重復(fù)點(diǎn)、x相同的點(diǎn);每次頂層循環(huán),求出以當(dāng)前為起點(diǎn)哪個(gè)直線(xiàn)上的點(diǎn)最多(斜率為0的為1條線(xiàn))
其中用到數(shù)學(xué)知識(shí),求最大公約數(shù),使用輾轉(zhuǎn)相除法。余數(shù)為0時(shí),小的那個(gè)為最大公約數(shù)。不為0時(shí),小的為余數(shù),大的為小的。
/**
 * Definition for a point.
 * struct Point {
 *     int x;
 *     int y;
 *     Point() : x(0), y(0) {}
 *     Point(int a, int b) : x(a), y(b) {}
 * };
 */
class Solution {
public:
    int maxPoints(vector<Point> &points) {
        
        if(points.size()<2) return points.size();
        
        int result=0;
        
        for(int i=0; i<points.size(); i++) {
            
            map<pair<int, int>, int> lines;
            int localmax=0, overlap=0, vertical=0;
            
            for(int j=i+1; j<points.size(); j++) {
                
                if(points[j].x==points[i].x && points[j].y==points[i].y) {
                    
                    overlap++;
                    continue;
                }
                else if(points[j].x==points[i].x) vertical++;
                else {
                    
                    int a=points[j].x-points[i].x, b=points[j].y-points[i].y;
                    int gcd=GCD(a, b);
                    
                    a/=gcd;
                    b/=gcd;
                    
                    lines[make_pair(a, b)]++;
                    localmax=max(lines[make_pair(a, b)], localmax);
                }

                localmax=max(vertical, localmax);
            }
            
            result=max(result, localmax+overlap+1);
        }
        
        return result;
    }

private:
    int GCD(int a, int b) {
        while (b) {
            int tmp = a%b;
            a = b;
            b = tmp;
        }
        return a;
    }
};
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問(wèn)題, 分享了一些自己做題目的經(jīng)驗(yàn)。 張土汪:刷leetcod...
    土汪閱讀 12,890評(píng)論 0 33
  • “復(fù)次,須菩提,菩薩于法,應(yīng)無(wú)所住行于布施。所謂不住色布施,不住聲、香、味、觸、法布施。須菩提,菩薩應(yīng)如是布施,不...
    木子哲學(xué)閱讀 417評(píng)論 0 1
  • 再見(jiàn) 章魚(yú)哥 我不知道該怎樣形容我的心情,或悲或驚或涼,到底還是自己做的孽,再苦也得自己嘗。 兩個(gè)人,不管是誰(shuí)用情...
    十三2002閱讀 194評(píng)論 0 0
  • 成甲:《好好學(xué)習(xí):個(gè)人知識(shí)管理精進(jìn)指南》作者 為什么學(xué)習(xí)思維模式能更好解決問(wèn)題?傳統(tǒng)思考方法:歸納法,復(fù)雜系統(tǒng)中有...
    夏娃她妹的簡(jiǎn)書(shū)閱讀 1,065評(píng)論 0 3

友情鏈接更多精彩內(nèi)容