算法准备-4.17
1. 完全平方数
-
描述:给定正整数 n,找到若干个完全平方数(比如
1, 4, 9, 16, ...
)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少 -
思路:动态规划
动态规划的核心将问题分解成小问题后,在计算规模较大的问题时,能够用到规模较小的问题的解;
我们建立一个整型数组res,res[i]表示的是n=i时的结果,计算第i+1时无非是比较当前的res[i+1]与减去平方数的res[i+1-k^2]+1中的最小值
-
题解:
class Solution { public int numSquares(int n) { int[] res=new int[n+1]; Arrays.fill(res,Integer.MAX_VALUE); res[0]=0; int i=0; for(i=0;i<n;i++) { if(i*i>=n) { break; } } int sqrt_index_value=i;//最大平方数的底 for(int k=1;k<=n;++k) { for(int j=1;j<=sqrt_index_value;++j) { if(j*j>k) break; res[k]=min(res[k],res[k-j*j]+1); } } return res[n]; } public int min(int a,int b) { if(a>=b) { return b; } return a; } }
2. 1-n整数中1出现的次数
-
描述:输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
-
未解思路:暴力解法:从1-n的数,全部逐个计算,对10取余,完事儿除以10,余数等于1,则计算结果的整型变量加一
-
题解1:
class Solution { public int countDigitOne(int n) { int res=0; for(int i=1;i<=n;i++) { int k=i; while(k!=0) { int over=k%10; if(over==1) { res+=1; } k=k/10; } } return res; } }
前几个用例并未出错,最后用例超出时间限制。
-
正确思路:将n分解成最高位high和剩下的数字last,如n=1234,high=1,pow=1000,last=234,1-999的1的个数为f(pow-1),1000-1234的1的个数为last(千分位的个数)+f(last);若high不等于1,结果等于pow+high*f(pow-1)+f(last);
-
题解2:
class Solution { public int countDigitOne(int n) { return f(n); } public int f(int n) { if(n<=0) { return 0; } String s=String.valueOf(n); int high=s.charAt(0)-'0'; int pow=(int)Math.pow(10,s.length()-1); int last=n-high*pow; if(high==1) return f(pow-1)+last+f(last)+1; else return high*f(pow-1)+pow+f(last); } }
这个主要就是找数学上的一个规律,与算法无关