题目1:202.快乐数
题目分析:
快乐数,题目中第二个描述很关键,它的意思说:要不就到1结束,要不就有个循环。没有其他他情况(这个可以用鸽巢原理(抽屉原理)来证明,这里限制了n<2.1*109–>n<9999999999,根据上面的算法计算得到数字变化范围在【1,810】,根据鸽巢原理,811次时,必定有一次重复。也就是成环)
这里我们把两种情况抽象为两个都后再后面会成环,第一种的环上全是1,第二种只有相交点相等,其他都不相等。我们把这道题抽象的理解为链表成环问题:思路就很清晰了,快慢指针。
思路1:快慢指针(数字版)
这次的快慢指针没有指针,也没有下标,而是数字。
代码实现:
class Solution { public: int func(int n) { int sum = 0; while (n) { int y = n % 10; sum += y * y; n = n / 10; } return sum; } bool isHappy(int n) { int slow = n; int fast = n; do { slow = func(slow); fast = func(func(fast)); } while (slow != fast); return slow == 1; } };
题目2:11.盛最多水的容器
题目分析:
盛水最多就是计算两个位置未成的体积。体积 = 两个位置小的那个高度 x 两个位置距离
利用单调性:公式:v = h * w
我们以 [6,2,5,4] 为例:开始计算第一个和最后一个围成的体积:v1= 4*3=12,然后我们可以发现,我们以两者中高度小的,来和两者之间的数来计算体积,发现宽度(w)对于v1来说一直在减小,高度最高为4,所以不管怎么计算这个体积都是小于v1的。于是就不用在考虑4和其他数组合了。
思路1:双指针(单调性)
代码实现:
class Solution { public: int maxArea(vector<int>& height) { int left=0,right=height.size()-1; int ret=0; while(left < right) { int v=min(height[left],height[right])*(right-left); ret= max(ret,v); if(height[left]<height[right]) ++left; else right--; } return ret; } };