#172
Factorial Trailing Zeroes
Given an integer n, return the number of trailing zeroes in n!.
Note: Your solution should be in logarithmic time complexity.
一个很直观的想法是用递归求出n!然后/10 计算末尾0的个数,但是不能AC。
换一种思路,末尾0来自于2*5,而对于任意一个正整数 n,1~n之间5的个数小于2的个数(间隔一个为2一个为5);
只要求出1~n之间所有数因式分解后5的个数:(即包括10,15,20,35....中的5)。具体过程如下:
-----> n! = (5 * 1) * (5 * 2) * (5
* 3)......* (5 * (min(n/5))) * (其他不能分解产生5的整数连乘,如3 4 7 8 等)
其中5的个数为
min(n/5) 【取下界】 ,再取剩余数(1*2*3*...min(n/5))中5的个数
------>n!/(5^(min(n/5)))
= 1 *2 *3 ....* min(n/5) = (5 * 1) * (5 * 2) * (5
* 3)......* (5 * (min(n/25))) * (其他不包含5的整数连乘)
其中5的个数为
min(n/25) 【取下界】 ,再取剩余数(1*2*3*...min(n/25))中5的个数
------>依次类推,最后得到5的个数为
min(n/5) + min (n/25) +......... 复杂度O(log5(n));
return
n/5
+ n/25
+ n/125
+ n/625
+ n/3125+...;
int trailingZeroes(int n) { //能被10整除多少次 int count=0; while(n) { count = count +n/5; n=n/5; } return count; }
#189 Rotate Array
Rotate an array of n elements to the right by k steps.
For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7]
is
rotated to [5,6,7,1,2,3,4]
.
旋转数组:这个题中 k具有周期性,周期为n, 也就是说 k>n 时 移动 k%n 步的移动结果 与移动 k 步的结果是一样的。
每个元素向前移动 k 步,(当然可以一次将所有元素移动一步,一共移动k次)
简单的想法是先保存一个原始数组,再将每个元素移动到其前面k个位置 算法如下:
或者是将数组分为 前numsSize-k个元素 和 后面 k 个元素两部分,然后把后面k个元素放到前面numsSize-k 个元素前面去。需要O(numsSize)空间
//10ms void rotate(int* nums, int numsSize, int k) { //一个一个移动,k可以大于numsSize int *a; <span style="white-space:pre"> </span>int i; k = k%(numsSize);//移动1倍时还原---周期性 a=(int *)malloc(sizeof(int)*numsSize); <span style="white-space:pre"> </span>if(k==0) <span style="white-space:pre"> </span>return; for(i = 0; i < numsSize; i++) <span style="white-space:pre"> </span>a[i] = nums[i]; for(i = 0; i < numsSize; i++) { nums[(i+k)%numsSize] = a[i]; } }
时间复杂度为 O(k%numsSize) 空间复杂度为 O(n),事实上,移动时,可以先保存数据,相当于先挖坑再填坑。以达到O(1) 的空间复杂度
nums[(i+k)%numsSize] = a[i];
还有一种 in-place的做法,原地数组转置,算法如下:
//12ms void reverse(int *nums, int left,int right) { int temp; while(left<=right) { temp = nums[left]; nums[left] = nums[right]; nums[right] = temp; left++; right--; } } void rotate(int* nums, int numsSize, int k) { k = k % numsSize; reverse(nums,0,numsSize-1); reverse(nums,0,k-1); reverse(nums,k,numsSize-1); }
#190 Reverse Bits
Reverse bits of a given 32 bits unsigned integer.
For example, given input 43261596 (represented in binary as 00000010100101000001111010011100), return 964176192 (represented in binary as00111001011110000010100101000000).
求二进制表示的32位无符号整数转置后的数。(每次通过 &1 取最低位 然后左移)
//4ms uint32_t reverseBits(uint32_t n){ int i,re=0; for (i = 0; i < 32; i++) re += (n >> i & 1)<<(31-i); return re; }
#191 Number of 1 Bits
Write a function that takes an unsigned integer and returns the number of ’1‘ bits it has (also known as the Hamming
weight).
For example, the 32-bit integer ’11‘ has binary representation 00000000000000000000000000001011
,
so the function should return 3.
求二进制数中1的个数,时间复杂度为O(k) k=log2(n) 为二进制数的位数
//0ms int hammingWeight(uint32_t n) { int count=0; while(n) { if(n&0x01==1) count++; n >>=1; } return count; }