简单的变换题解
30分解法
n范围只有1e6,可以用时间复杂度o(n)的做法,比如递推打表等等,时间复杂度o(n),空间复杂度o(n)。
100分解法
其实不难发现直接模拟本过程即可,时间复杂度即为o(logn),因为每到奇数就会一次操作到偶数,每到偶数就能使n指数级下降,所以时间复杂度o(logn),唯一比较麻烦的地方就是无限循环的,这样直接模拟无疑会TLE。这里提供两种处理的方法:
1.走到必定会死循环的点自动终止
由于每次都只能到达n-3或者n-2这两个点,所以可以得出一个结论,n必然会到达n=1,n=2,n=3三种情况之一,其中n=1,n=2是必定死循环的,递归到这里直接break返回-1即可,递归到n=3只要返回递归次数+1即可(因为从n=3到n=0还需要一步操作)。时间复杂度o(logn),空间复杂度o(logn)(递归logn次系统分配logn大小空间),代码如下:
int ans=0; void dfs(long long x) { ans++; if(x<3)ans=-1; else if(x==3); else { if(x%2)dfs(x-3); else dfs(x/2); } } class Solution { public: /** * * @param n long长整型 * @return int整型 */ int Numberofoperations(long long n) { // write code here dfs(n); return ans; } };
相同逻辑,补充一下验题人给出的非递归做法,走到负数就一定死循环跳出,逻辑和上面的做法几乎完全一致:
class Solution { public: /** * * @param n long长整型 * @return int整型 */ int Numberofoperations(long long n) { // write code here for(int cnt=0;n>=0;cnt++) if(!n) return cnt; else if(n&1) n-=3; else n/=2; return -1; } };
2.走到一定数量还没有跳出递归则强制跳出递归并输出-1
由于前面对时间复杂度的分析,递归次数最多2*logn次, 所以递归次数超过2*logn,即说明陷入死循环了,直接跳出递归输出-1即可。时间复杂度o(logn),空间复杂度o(logn)(递归logn次系统分配logn大小空间),代码如下:
int ans=0; void dfs(long long x) { if(x==0)return ; ans++; if(ans>200)return ; if(x%2)dfs(x-3); else dfs(x/2); } class Solution { public: /** * * @param n long长整型 * @return int整型 */ int Numberofoperations(long long n) { // write code here dfs(n); if(ans<200) return ans; else { ans=-1; return ans; } } };