0
点赞
收藏
分享

微信扫一扫

【LeetCode】到达终点数字

沉浸在自己的世界里 2022-05-03 阅读 61

到达终点数字

思路

  • 假设第1…, i 次均向右移动,那么移动的步数分别为1,2,3,…,i步;
  • 假设第1…, i 次均向左移动,那么移动的步数分别为-1,-2,-3,…,-i步;
  • 因此第1…, i 次的某次选择向左或向右移动,移动的总步数的差值分别为-2,-4,-6,…,-2i步;
  • 假设移动到终点target位置,最多需要target步,那么可以根据二分迭代搜索需要的最小移动次数;
    • 搜索起始边界L,R分别为0,target,对应的每次搜索的中间位置m=(L+R)/ 2, 搜索停止条件L > R,定义到达target位置附近所需要的移动次数为 near;
    • 从1一直加到m的和,设为sum(m);如果sum(m) >= target,则更新near = m,直到停止搜索为止;
    • 如果此时的sum(near) 恰好等于target,则near就是要找的最小移动次数;
    • 如果此时的sun(near) > target,也即移动的总步数超出了target,建设此时超出的步数为diff = sun(near) - target
    • 如果diff为偶数,也即需要之前的某一步向左移动即可满足(参考第三条差值),那么可以直接返回near。
    • 如果diff为奇数,就需要near再向右移动,因为无论如何调整之前的某一步方向,不会改变sum(near)的奇偶性,也就不会改变diff的奇偶性,也就到不了target位置;
    • 那near再向右移动多少步呢?好问题。观察一下sum(m)的数值,【1,3,6,10,15,21,28,36】奇奇偶偶奇奇偶偶 交替出现,因此最多再移动两步就可以改变sum(near)的奇偶性,也即改变了diff的奇偶性。

代码

Python

class Solution:
    def sum(self, m):
        return int((m * (m+1))/2)

    def reachNumber(self, target: int) -> int:
    
        target = abs(target)
        l, r = 0, target
        m, near = 0, 0
        while l <= r:
            m = int((l + r)/2)
            if self.sum(m) >= target:
                near = m
                r = m - 1
            else:
                l = m + 1
        if self.sum(near) == target:
            return near
        
        # 差值为奇数  sum和规律 奇奇偶偶奇奇偶偶 交替,因此循环两次
        if ((self.sum(near) - target) & 1) == 1:
            near += 1
        
        if ((self.sum(near) - target) & 1) == 1:
            near += 1

        return near

Java

public class ReachNumber {

	public static int reachNumber(long target) {
		if (target == 0) {
			return 0;
		}
        target = Math.abs(target);
		long l = 0;
		long r = target;
		long m = 0;
		long near = 0;
		while (l <= r) {
			m = (l + r) / 2;
			if (sum(m) >= target) {
				near = m;
				r = m - 1;
			} else {
				l = m + 1;
			}
		}
		if (sum(near) == target) {
			return (int)near;
		}
		if (((sum(near) - target) & 1) == 1) {
			near++;
		}
		if (((sum(near) - target) & 1) == 1) {
			near++;
		}
		return (int)near;
	}

	public static long sum(long n) {
		return (n * (n + 1)) / 2;
	}

}
举报

相关推荐

0 条评论