int x =0; for(int i=0;i<size;i++)x=x*10+str.charAt(i)-'0';
变量交换
如何不使用第三个变量来交换两个数的值 ?
数学
1 2 3 4
a=10,b=20 a=a+b=30 b=a-b=30-20=10 a=a-b=30-10=20
位运算(异或)
1 2 3 4
a=10,b=20 a=a^b b=a^b a=a^b
最小公倍
1 2 3 4 5 6 7 8 9 10 11
publicintcommonMultiple(int n, int m) {// 求两个数的最小公倍数 return n * m / commonDivisor(n, m); } publicintcommonDivisor(int n, int m) {// 求两个数的最大公约数 while (n % m != 0) { intt= n % m; n = m; m = t; } return m; }
1.欧几里得算法又称辗转相除法,是指用于计算两个非负整数a,b的最大公约数。应用领域有数学和计算机两个方面。计算公式 **gcd(a,b) = gcd(b,a mod b) **。
以除数和余数反复做除法运算,当**余数为 0** 时,取当前算式**除数**为最大公约数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
class Solution{ //递归 public int gcd(int num1,int num2){ int mod = num1 % num2; return mod ==0 ? num2 : gcd(num2,mod); } //迭代 public int gcd(int num1,int num2){ int mod = num1 % num2; while(mod!=0){ num1 = num2; num2 = mod; mod = num1 % num2; } return num2; } }
class Solution{ public int gcd(int num1, int num2) { int max = Math.max(num1, num2); int min = Math.min(num1, num2); int count =0; while (max %2==0&& min %2==0) { max /=2; min /=2; count++; } int reduce = max - min; while (reduce != min && reduce >0) { max = Math.max(min, reduce); min = Math.min(min, reduce); reduce = max - min; } return (int) (min * Math.pow(2, count)); } }
class Solution { //摩尔投票:遇到和当前统计的num则count++,否则count--,当count==0,更新num public int majorityElement(int[] nums) { int n = nums.length; int num = nums[0]; int count =1; for(int i=1;i<n;i++){ if(nums[i]==num)count++; else count--; if(count ==0){ num = nums[i]; count++; } } return num; } }
Random rand; List<Integer> arr;//累计每个矩阵点数[rect(1)Points,rect(1)Points+rect(2)Points,....,rect(N-1)Points+rect(N)Points] int[][] rects; //预处理 publicSolution(int[][] rects) { rand = newRandom();//随机种子 arr = newArrayList<>(); arr.add(0);//默认添加0,数据从下标1开始 this.rects = rects; //预处理 for (int[] rect : rects) { inta= rect[0], b = rect[1], x = rect[2], y = rect[3]; //当前矩阵的点数 inttotalPoints= (x - a + 1) * (y - b + 1); //前一个点的矩阵总共有的点数 IntegerprevRectPoints= arr.get(arr.size() - 1); //当前总共有的点 arr.add(prevRectPoints + totalPoints); } }
publicint[] pick() { //1.在[0,所有点数]区间获取一个随机整数(保证了所有的点等概率获取) intk= rand.nextInt(arr.get(arr.size() - 1)); //2.在arr数组中获取点数为k所在矩阵数组的下标(k+1是因为rand是会取0的,但是我们points不可能为0) intrectIndex= binarySearch(arr, k + 1) - 1; //3.k=k-arr.get(rectIndex)得到当前k点是在矩阵中的第几个点(注意这里的rectIndex是当前矩阵的前面一个矩阵的下标,因为我们上面存的时候是从下标1开始) k -= arr.get(rectIndex); //当前随机获取的矩阵 int[] rect = rects[rectIndex];//因为已经减一了,所以当前rectIndex就是对应数组的矩阵 //还原坐标 inta= rect[0], b = rect[1], y = rect[3]; intcol= y - b + 1;//列上有多少个点,算上边框 intda= k / col;//x上的增量 intdb= k - col * da;//y上的增量 //左下角坐标加上增量da、db即可 returnnewint[]{a + da, b + db}; }
int[] w; int n; long[] prefixSum; long total; public Solution(int[] w) { this.w = w; this.n = w.length; total = w[0]; prefixSum = new long[n]; for (int i = 1; i < n; i++) { total+=w[i]; prefixSum[i]+=prefixSum[i-1]; } } //[20, 34, 160, 2] //[20, 54, 210, 212] //[1,20],[21,54],[55,210],[211,212] public int pickIndex() { //[1,total] int index = (int) (Math.random() * total) + 1; //获取当前随机数所属区间的下标 int ret = binarySearch(index); return ret; }
private int binarySearch(int index) { int left = 0,right = prefixSum.length - 1; while (left<right){ int mid = left + (right-left)/2; if (prefixSum[mid]>=index)right = mid; else if (prefixSum[mid]<index){ left = mid + 1; } } return left; }
class Solution { //分析 //5!=[5]*4*3*[2]*1=1201个0 //10!=[10]*9*8*7*6*[5]*4*3*[2]*1=36288002个0 //15!=[15](拆分3*5然后5*2又组成一个0)*14*13*12*11*[10]*9*8*7*6*[5]*4*3*[2]*1=13076743680003个0 //结论:能出现0的情况只有2*5的倍数(25*4=100可拆解为2*5*2*5同样是两个0),所以只需要求出其乘法因子有多少个5即可 public int trailingZeroes(int n) { int ret =0; if(n<5)return0; while(n>=5){ ret+=n/5; n/=5; } return ret; } }