day24
1.剑指 Offer 14- I. 剪绳子
2=1+1,3=1+2,
4 = 2 + 2,5 = 3 + 2,6 = 3 + 3,7 = 3 + 4,8 = 3 + 5 = 3 + 3 + 2,9 = 5 + 4 = 3 + 2 + 4. . . . . .
可以发现,其实从4开始,每个数字都可以由2和3组成,尽可能的多分出一些3乘积就会大些
举个栗子:8 = 3 + 5,当3和5(3 + 2)各自的乘积取最大值,两者再相乘那么8就会取得乘积的最大值。同样的每个数字都可以这样拆分,每个拆分出来的数分别取得乘积的最大值,把这些最大值相乘就得到我们要求的(有种动态规划的感觉,就是这个数的最大乘积取决于 前面组成它的数 的最大乘积)
2和3要单独处理,因为它们不得不 要拆分出一个1来,while(n - 3 > 1) ,这个条件是,如果最后剩下的n不大于4,就直接相乘。为什么如果最后是4要直接退出循环乘4呢,因为最后4继续减3处理的话4会被拆分成4 = 3 +1;但是中间不能直接减去一个4然后乘4,只有最后只剩下4的时候才可以(5 = 3 + 2,5 = 4 + 1;6 = 3 + 3,6 = 4 + 2,都是前者更大)
1 class Solution { 2 public: 3 int cuttingRope(int n) { 4 if(n <= 3) return n - 1; 5 int res = 1; 6 while(n - 3 > 1){ //一直减3,减一个3就乘一个3 7 res *= 3; 8 n -= 3; 9 } 10 res = res * n; 11 return res; 12 } 13 };
2.剑指 Offer 57 - II. 和为 s 的连续正数序列
看到连续,就想到双指针
1 class Solution { 2 public: 3 vector<vector<int>> findContinuousSequence(int target) { 4 vector<vector<int> > res; 5 int i = 1,j = 2,s = 3; 6 while(i < j){ 7 if(s == target){ 8 vector<int> ans; 9 for(int k = i;k <= j;k ++) 10 ans.push_back(k); 11 res.push_back(ans); 12 } 13 if(s < target){ //注意if和else里两条语句的顺序 14 j ++; 15 s += j; 16 } 17 else{ 18 s -= i; 19 i ++; 20 } 21 } 22 return res; 23 } 24 };
3.剑指 Offer 62. 圆圈中最后剩下的数字
约瑟夫环问题
1)暴力解法(会超时,不建议)
1 class Solution { 2 public: 3 int flag[100001]; 4 int lastRemaining(int n, int m) { 5 if(n == 1) return 0; 6 int cnt1 = n - 1,cnt2 = 0; 7 while(cnt1){ 8 for(int i = 0;i < n;i ++){ 9 if(flag[i] == 0){ 10 cnt2 ++; 11 if(cnt2 == m){ 12 flag[i] = 1; 13 cnt2 = 0; 14 cnt1 --; 15 if(cnt1 == 0) break; 16 } 17 } 18 } 19 } 20 for(int i = 0;i < n;i ++) 21 if(flag[i] == 0) 22 return i; 23 return 0; 24 } 25 };
2)问题用f(n,m)表示 ,表示n个数时,数到m时删除那个数后剩下的最终的编号(位置序列)(不是指具体某个数,而是一排数!!!)
结合下面两篇题解理解
假设n = 11,m = 3,有 0,1,2,3,4,5,6,7,8,9 一共10个数字
 
f(1,3)是最后留下来的数的位置,也就是我们要求的。我们一步步的回退,找到这个数在最原始的一排数里的位置,比如这个例子:第一次回退找到这个数在f(2,3)时的位置:1,再回退,找到它在f(3,3)时的位置:1,再回退,找到它在f(4,3)时的位置:0,最后一次回退,找到它在f(5,3)时的位置:3,在最原始一排数(0,1,2,3,4)中,底数3对应的数是3
 
1 class Solution { 2 public: 3 int lastRemaining(int n, int m) { 4 if(n == 0) return 0; 5 return (lastRemaining(n - 1,m) + m) % n; 6 } 7 };
也可直接从0开始递推
1 class Solution { 2 public: 3 int lastRemaining(int n, int m) { 4 int x = 0; 5 for (int i = 2; i <= n; i++) { 6 x = (x + m) % i; 7 } 8 return x; 9 } 10 };
注:我们求出的是数在数组中对应的位置,也就是说,如果位置上 对应的数 和位置数不同,我们要输出位置上的那个数,而不是输出位置数。比如我们刚刚上面那个例子(0,1,2,3,4),位置3对应的数字是3,我们就输出3,如果给出的数组是(6,3,8,9,7),位置3对应的是9,我们应该输出9
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号