您的位置:首页 > 其它

算法中常见的Math类问题总结(一)

2016-09-28 14:32 162 查看

算法中Math(数学类问题总结一)

Nim Game(分石头),A和B轮流分石头,每人每次只能分1到3个,什么样的策略可以保证A总是赢的。

思路:若是A第一个拿并且总的石头数多于3,那么希望最终留下的是4个,因为剩4个时,无论B怎么拿,A都是赢的。若B第一个拿,那么希望最终剩下的永远不要是4。道理同上。

If(n%4==1 || n%4==2 || n%4==3) return 1; else return 0;

求两个数之和,但是不能使用+或者-。

思路:既然题目要求不能用+或者—,那么只能换种方式,最直接的就是想到用异或运算和&运算。若某位上的两个数同时为1或者0,则异或后为0,若一个1,一个0,则异或后是1,这是加法运算中得到的正确结果。但是没有考虑进位,当同时为1时,该为为0,但需要进位,此时我们再求两个数的&运算,即为进位,并左移一位,讲这个数和上面异或得到的数再递归上述类似的运算,直到&运算后为0,即没有进位为止。

getSum{ if(b==0) return a; c=a^b; d=a&b; getSum(c,d);}

Single Number(在一个整数数组中,每个数都出现两次,只有一个数只出现了一次,找出这个数)

思路:这种题目求和不行,最直接想到的就是进行位运算,再考虑用哪种位运算,我们知道两个相同的数做^运算为0,那么将所有的数做异或运算后,得到的就是只出现一次的那个数了。由此题会引出很多类似的问题,大多都是不同的位运算结合来实现的。

Majority Element(找出整个数组中出现频率最高的那个整数,并且出现的次数多于[n/2],并且)假设总有这样的数存在的,个数多[n/2]的只有一个数。

思路1:这道题最简单的做法就是先给数组排序,然后统计相等元素的个数,找出最多的那个。但是这样时间复杂度太高,至少是O(nlogn)。

思路2:用哈希表实现。用map存储,数组中的当前元素的值为key,对应的他出现的次数为value,那么最后找个value大与[n/2]的元素即可。

思路3:位运算。假设数据的数值范围是(1,2^32-1),那么我们可以用32位来表示任何一个数。也就相当于一个大小为
4000
32的数组来标记各个元素在每个位上出现的次数,最后将32位中次数大于[n/2]的删选出来,转换为十进制,即为所求。

Contains Duplicate(判断数组中是否存在重复的两个元素,若有返回ture,否则false)。

思路:这道题很简单,用set或者hashmap都可以快速实现。Set中每个元素只出现一遍,最后判断set的大小和数组的大小是否一样即可。而map可以判断是否已经存在这个元素就OK啦。

Add Digits(求数字各个位之和,直到变为一个数为止。例如:38: 3+8=11;1+1=2)

思路:这题目刚开始看上去,我能想到的就是循环或者递归了,一次一次的遍历求,但是题目的要求确是不能用any loop or recursion。然后就蒙了,想了很久没思路。但是这种题肯定是存在某种规律的,在1到9之间不停地循环。之后看了大神们的解答,果然是这样。0单独考虑外,从1开始,数字之和不停地在1到9之间循环,那么如果这个数是9的倍数,他的最终结果是9,其他的就是n%9的结果了。原来如此简单,功夫不够,还得多练啊。

If(n==0) return 0; m = n%9; if(m==0) return 9; else return m;

Move Zeros(把一个数组中的0全部挪到最后面去,保持数组其他元素的相对位置不变,例如:nums=[0,1,0,3,12]),最后得到nums=[1,3,12,0,0]; 并且只能用替换的方法实现。

思路:这道题很简单,设置两个指针,从头开始,一个是遍历旧数组,遇到一次判断是不是0,另一个负责记录新的数组,讲不是0的全部替换到该指针指向的当前位置。如下:

( A -> 1; B -> 2; C -> 3 … Z -> 26 AA -> 27 AB -> 28)

思路:这道题其实和十进制的规律一模一样,变形的26进制数。给了一个字符串,计算得到是第几列,也就是把字符串转化为对应的整数。(a[0]-‘A’+1)26+(a[1]-‘A’+1); 更直白的表达:如果是十进制的数1342: 1(10^3)+3*(10^2)+4*(10^1)+2+(10^0); 对应于二十六进制的数: ABCD:1*(26^3)+2*(26^2)+3*(26^1)+4*(26^0).

Power of Two(判断一个数是不是2的幂) num&(num-1) == 0 (这个最简单)

思路1:第一反应想到的应该是二进制,把2,4,8,16,32等2的幂转换成2进账可以发现,最高位为1,后面的全部为0。根据这个规律我们可以把n转换为二进制的字符串,此时最低位对应的数字里的最高位,我们只需要判断最低位是否为1,并且其他为是否全部为0。

思路2:判断一个数的幂可以转换为对数来算,用换底公式,log以10为底的n除以log以10位底的2,此时是double型的,减去它的int型,看是否为0,若是整数,则是2的幂。

注意:由于整数的最小值即Integer.MinValue转换为二进制是不是正常的,需要单独考虑,直接返回false。写这种数字题时,切记注意考虑0,1,最大最小数这些敏感的数,做到万无一失。

Power of Three(判断一个数是不是3的幂)

思路: 同上,用对数的方法判断。

Power of Four(判断一个数是不是4的幂)

思路:除了上面的换地公式,我们还可以借鉴2的思路来考虑这道题。

首先先判断是不是2的幂,是2的幂之后再判断与10101010101 做&运算是不是其本身。

Happy Number(这道题定义了一种快乐数,就是说对于某一个正整数,如果对其各个位上的数字分别平方,然后再加起来得到一个新的数字,再进行同样的操作,如果最终结果变成了1,则说明是快乐数,如果一直循环但不是1的话,就不是快乐数,那么现在任意给我们一个正整数,让我们判断这个数是不是快乐数。)

思路:拿到这种题用肉眼看不出思路,那么就多试几个数,找找规律。果然会发现,在循环中必定会出现1和4,而且4继续循环的话还会回到4,重复上述过程,这时的数就不是快乐数了,直接返回false,若是1的话就返回true;当然,如果没发现这个规律的话,我们可以用set,将每次得到的结果保存起来,若是再出现的话那一定是开始循环了,则返回,否则继续。这种题,如果要是用很严格的数学证明结论的话,那比较难,希望有一天可以达到这种水平。

Ugly Number(定义为一个数的质因素只包含2,3,5)

思路:这道题很简单,最直接的思路就是直接用该数不停地除以2,直到不能整除为止,同理,再除以3,5。看最终结果是不是为1。

Number of 1 bits(一个无符号整数,返回其二进制形式中包含的1的个数)

思路:位运算。每次判断整数n的最后一位是不是1,即让n&1,之后将n右移一位。直到n=0。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法-Math leedcode