leetcode day2
【参考】http://book.2cto.com/201210/5663.html
【参考】http://www.cnblogs.com/exponent/articles/2141477.html
nim game定义【292】:
Nim是一种两个人玩的游戏,玩家双方面对一堆硬币(或者石头或者豆粒)。假设有k≥1堆硬币,每堆分别有n1,n2,…,nk枚硬币。这一游戏的目标就是取得最后一枚硬币。游戏的规则如下:
(1)玩家轮番出场(我们称第一个取子的玩家为Ⅰ,而第二个玩家为Ⅱ)。
(2)当轮到一个玩家取子时,他们都要从选择的硬币堆中至少取走一枚硬币。(这位玩家也可以把所选硬币堆的硬币都取走,于是剩下一个空堆,这时它“退出”。)
当所有硬币堆都空了的时候,游戏结束。走最后一步的玩家,即取走最后一枚硬币的玩家获胜。
在这个游戏中的变量是堆数k和堆中的硬币数n1,n2,…,nk。我们要问的组合问题是确定是第一个玩家胜还是第二个玩家胜1,以及这位玩家为了获胜应该如何取子,也就是获胜策略。
为了进一步理解Nim游戏,下面我们考虑一些特殊的情况2。如果一开始就只有一堆硬币。那么玩家Ⅰ取走所有硬币就可以获胜。现在假设k=2,且分别有n1枚和n2枚硬币。玩家Ⅰ是否可以获胜不取决于n1,n2具体是多少,而是取决于它们是否相等。假设n1≠n2。玩家Ⅰ可以从大堆中取走足够多的硬币以便对于玩家Ⅱ来说,剩余两堆的大小相同。现在,当轮到玩家Ⅰ时,他可以模仿玩家Ⅱ的取子方式。因此,如果玩家Ⅱ从一堆中取走了c枚,那么玩家Ⅰ则从另一堆中取走相同数目的硬币。这样的策略保证玩家Ⅰ可以获胜。如果n1=n2,那么玩家Ⅱ通过模仿玩家Ⅰ的取子方式而获胜。因此,我们就完全解决了2堆的Nim游戏的取子问题。下面是2堆Nim游戏的一个例子,其堆的大小分别是8和5:
上述解决2堆Nim游戏的想法是用某种方式取子使得剩余两堆的大小相同,这一想法可以推广到任意k堆的情况。
把nim每堆的数字用二进制表示,然后位数对齐进行异或运算,如果全0则说明是game是平衡的,否则是非平衡的。
若一个Nim游戏不是平衡的,则称它为非平衡的(unbalanced)。我们说第i位是平衡的,指的是和ai+bi+…+ei是偶数,否则就是非平衡的。因此,若一个游戏是平衡的,则它在各个位上都是平衡的,而对于非平衡游戏来说,至少存在一个非平衡位。
于是我们有下面的陈述:
玩家Ⅰ(先出手的)能够在非平衡Nim游戏中获胜,而玩家Ⅱ(后出手的)则能够在平衡Nim游戏中获胜。
为了理解上述的结论,我们扩展2堆Nim游戏中使用的策略。假设这个Nim游戏是非平衡的。设最大不平衡位是第j位。于是,玩家Ⅰ以某种方式取走硬币给玩家Ⅱ留下一个平衡游戏。他的作法是:选出一个第j位上是1的堆,并从中取走一定数目的硬币使得剩下的游戏是平衡的(参见练习题32)。无论玩家Ⅱ怎样做,他都不得不又给玩家Ⅰ留下一个不平衡的游戏,玩家Ⅰ又把这个游戏变成平衡游戏。如此这般继续下去就可以保证玩家Ⅰ获胜。如果这个游戏开始时就是平衡游戏,那么玩家Ⅰ第一次取子使其变成不平衡游戏,此时轮到玩家Ⅱ采用平衡游戏的策略。
23 = 8 |
22 = 4 |
21 = 2 |
20 = 1 |
|
大小为7的堆
|
0
|
1
|
1
|
1
|
大小为9的堆
|
1
|
0
|
0
|
1
|
大小为12的堆
|
1
|
1
|
0
|
0
|
大小为15的堆
|
1
|
1
|
1
|
1
|
23 = 8 |
22 = 4 |
21 = 2 |
20 = 1 |
|
大小为7的堆
|
0
|
1
|
1
|
1
|
大小为9的堆
|
1
|
0
|
0
|
1
|
大小为12的堆
|
0
|
0
|
0
|
1
|
大小为15的堆
|
1
|
1
|
1
|
1
|
归根结底,Nim取子游戏的关键在于游戏开始时游戏处于何种状态(平衡或非平衡)和第一个游戏人是否能够按照取子游戏的获胜策略来进行游戏。
leetcode上的nim游戏是只有一堆硬币,并且每次取硬币的个数(小于等于3个,至少1个)有限制的特殊情况,
public boolean canWinNim(int n) { if (n <= 0) {return false;} return n % 4 != 0; }
explanation:
- According to the hint, we know that if n = 4, no matter how many stones I remove, I lose. If n = 5, I can remove one stone and there are 4 stones for another player. Thus, I win. Similarly, if n = 6 or 7, I can remove 2 or 3 stones and i win finally.
- If n = 8, no matter how many stones I remove, there are 7 or 6 or 5 stones for another player, s/he can remove stones as we said before and then wins.
- If n = 9 or 10 or 11, I can leave 8 stones to another player, then I win.
- If n = 12, I can leave 9, 10 or 11 stones to another player. Then, s/he can leave 8 stones to me, then I lose. ......
- The rule is: if (n % 4 == 0) then I lose.
Add Digits【258】:
Given a non-negative integer num
, repeatedly add all its digits until the result has only one digit.
For example:
Given num = 38
, the process is like: 3 + 8 = 11
, 1 + 1 = 2
. Since 2
has only one digit, return it.
Could you do it without any loop/recursion in O(1) runtime?
维基百科:一个整数的数字和,是把它的所有数字相加起来所得的和。例如,84001的数字和是8+4+0+0+1 = 13。
这个概念与数字根有密切的关系,但并不相同,数字根是把所有数字相加起来所得的和,然后再把这个和的所有数字相加起来,又得到一个和,重复这个步骤,直到最终只剩下一个数字,这个数字便称为数字根。数字和可以是任意的值,而数字根只能是1到9。
解题思路:数字根是有规律的,因为数字跟是不大于9的,所以可以通过求9的余数,即可得到数字跟。题目要求不用循环,时间复杂度为常数
public class Solution { public int addDigits(int num) { if(num==0)return num; else return num%9==0?9:num%9; /*下面的方法时间不符合要求,执行了14ms if(num<10){ return num; } while(num>10){ String aS = String.valueOf(num); char[] asC = aS.toCharArray(); for(int i=0;i<asC.length;i++){ num+=asC[i]; } } return num;*/ } }
Maximum Depth of Binary Tree【104】:
Given a binary tree, find its maximum depth.
思路:使用递归,给一个节点,如果还有子节点,则深度加1
public class Solution { public int maxDepth(TreeNode root) { //注意root的判空,还有当只有一个节点的时候,返回的数值应该是1,所以注意加1 return (root == null)?0:Math.max(1+maxDepth(root.left),1+maxDepth(root.right)); } }
【237】Delete Node in a Linked List
Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.
Supposed the linked list is 1 -> 2 -> 3 -> 4
and you are given the third node with value 3
, the linked list should become 1 -> 2 -> 4
after calling your function.
思路:这是个单链表,给了要删除的结点,既然我们无法拿到他的前驱结点,不能按照一般的的方法删除结点,所以就让要删除的结点变成下一个结点,然后把下一个结点删除了
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class Solution { public void deleteNode(ListNode node) { if(node==null)return; else if(node.next==null)return; else{ node.val = node.next.val; node.next = node.next.next; } } }