12. 数学


1. 位运算
2. 10进制进位,取余
3. 找规律题目

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。可以得出,只出现一次的数字。
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的升级版,可以使用32bit保存对应每个bit之和取余进行操作。对重复出现的那个的值进行取余,如本题中的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.
  • 使用位运算实现除法
  • 主要思想是倍数可以用2的指数和求出
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).
不适用位运算时间复杂度为O(n),使用位运算时间复杂度为O(logn)
使用位运算的关键是理解将某个数值拆分成二进制表示的形式,如 9的二进制表示为 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记录一般数目,只能在原地进行运算。其实也是移位,不过是10进制的。遍历次数降低一半且空间复杂度为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.
实现atoi函数,需要注意的是 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
解析: 数组的下一个字典顺序
边界:数组大小小于2
思路:找规律的题目,1. 从后往前找第一个相邻的构成升序的p[n] < p[n+1],n点为违法点。2. 对p[n]之后的元素进行逆序 3. 在排序后的p[n+1]至最后的第一个大于p[n]的元素与p[n]交换
C++ STL中下一个字典顺序的函数,next_permutation(beg, end)
时间复杂度: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]构成的第k个数列,可以使用31题中的方法一步一步来,也可以根据规律去做。规律如下:第一位为每(n-1)!为1组,则res[0]为nums[k/(n-1)!]。剩下的n-1个数组也是这个规律。每次需要更新k和count,k %= count(含义为该组中第k个)。
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.
罗马数字转换成阿拉伯数字,主要是找出每个罗马数字对应的大小
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 ]
]
找出规律!!!实现要细心
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?
将数组旋转2次,一次是水平或垂直,一次是斜着沿着轴。顺序无关
/*
 * 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.
找出一条直线上最多的点
这种题最怕的就是直接被吓到,没思路。其实一步步挨个遍历,下层循环遍历剩余点即可。顶层循环下,当前点做起点,建立最大公约数的map,记录重复点、x相同的点;每次顶层循环,求出以当前为起点哪个直线上的点最多(斜率为0的为1条线)
其中用到数学知识,求最大公约数,使用辗转相除法。余数为0时,小的那个为最大公约数。不为0时,小的为余数,大的为小的。
/**
 * 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;
    }
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,719评论 0 33
  • “复次,须菩提,菩萨于法,应无所住行于布施。所谓不住色布施,不住声、香、味、触、法布施。须菩提,菩萨应如是布施,不...
    木子哲学阅读 270评论 0 1
  • 再见 章鱼哥 我不知道该怎样形容我的心情,或悲或惊或凉,到底还是自己做的孽,再苦也得自己尝。 两个人,不管是谁用情...
    十三2002阅读 172评论 0 0
  • 成甲:《好好学习:个人知识管理精进指南》作者 为什么学习思维模式能更好解决问题?传统思考方法:归纳法,复杂系统中有...
    夏娃她妹的简书阅读 982评论 0 3