LintCode:剑指Offer
Posted 不闻余物
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LintCode:剑指Offer相关的知识,希望对你有一定的参考价值。
第1章:
9.Fizz Buzz :http://www.lintcode.com/zh-cn/problem/fizz-buzz/
解法1:(% String.valueOf)
(1.rst; 2.for(1,n),15,5,3,else; 3.return)
1 public class Solution { 2 public List<String> fizzBuzz(int n) { 3 List<String> rst = new ArrayList<>(); 4 for (int i = 1; i <= n; i++) { 5 if (i % 15 == 0) rst.add("FizzBuzz"); 6 else if (i % 5 == 0) rst.add("Buzz"); 7 else if (i % 3 == 0) rst.add("Fizz"); 8 else rst.add(String.valueOf(i)); 9 } 10 return rst; 11 } 12 }
解法2:(利用两个变量fizz和buzz计数,为3、5的时候则add Fizz和Buzz并清零。不需要使用%)
1 public class Solution { 2 public List<String> fizzBuzz(int n) { 3 List<String> ret = new ArrayList<String>(n); 4 for(int i=1,fizz=0,buzz=0;i<=n ;i++){ 5 fizz++; 6 buzz++; 7 if(fizz==3 && buzz==5){ 8 ret.add("FizzBuzz"); 9 fizz=0; 10 buzz=0; 11 }else if(fizz==3){ 12 ret.add("Fizz"); 13 fizz=0; 14 }else if(buzz==5){ 15 ret.add("Buzz"); 16 buzz=0; 17 }else{ 18 ret.add(String.valueOf(i)); 19 } 20 } 21 return ret; 22 } 23 }
第2章:
366.Fibonacci: http://www.lintcode.com/en/problem/fibonacci/
解法:<Iterative><Two Pointers>(指针a指向第一个数,指针b指向第2个数,for循环a,b分别向后移动,返回a)
(1.a,b; 2.for(1,n),tmp,b,a; 3.return)
1 class Solution { 2 /** 3 * @param n: an integer 4 * @return an integer f(n) 5 */ 6 public int fibonacci(int n) { 7 // write your code here 8 int a = 0, b = 1; 9 for (int i = 1; i < n; i++) { 10 int tmp = b; 11 b = a + b; 12 a = tmp; 13 } 14 return a; 15 } 16 }
204.Singleton: http://www.lintcode.com/en/problem/singleton/
单例:
1 class Solution { 2 /** 3 * @return: The same instance of this class every time 4 */ 5 public static Solution instance = null; 6 public static Solution getInstance() { 7 if (instance == null) { 8 instance = new Solution(); 9 } 10 return instance; 11 } 12 };
212.Space Replacement:http://www.lintcode.com/en/problem/space-replacement/
空格替换:
解法:<Two Pointers>(先for循环遍历得到newLen;i指向原数组从后向前移动,j指向新数组从后向前移动。非space的时候就把i的值给j指向位置,遇到space的时候就依次是02%来替换。)
(1.cnt,for-if(); 2.newLen,j; 3.for(length-1),if()-[nL-j++]=[i]; 4.else-02%; 5.return)
1 public class Solution { 2 /** 3 * @param string: An array of Char 4 * @param length: The true length of the string 5 * @return: The true length of new string 6 */ 7 public int replaceBlank(char[] string, int length) { 8 // Write your code here 9 int cnt = 0; 10 for (int i = 0; i < length; i++) { 11 if (string[i] == \' \') cnt++; 12 } 13 int newLen = length + cnt * 2; 14 int j = 1; 15 for (int i = length - 1; i >= 0; i--) { 16 if (string[i] != \' \') { 17 string[newLen - j++] = string[i]; 18 } 19 else { 20 string[newLen - j++] = \'0\'; 21 string[newLen - j++] = \'2\'; 22 string[newLen - j++] = \'%\'; 23 } 24 } 25 return newLen; 26 } 27 }
public class Solution { /** * @param string: An array of Char * @param length: The true length of the string * @return: The true length of new string */ public int replaceBlank(char[] string, int length) { // Write your code here int cnt = 0; for (int i = 0; i < length; i++) { if (string[i] == \' \') { cnt++; } } int newLen = length + 2 * cnt; int j = newLen - 1; for (int i = length - 1; i >= 0; i--) { if (string[i] != \' \') { string[j--] = string[i]; } else { string[j--] = \'0\'; string[j--] = \'2\'; string[j--] = \'%\'; } } return newLen; } }
365.Count 1 in Binary: http://www.lintcode.com/en/problem/count-1-in-binary/
二进制中1的个数:<Bit Manipulation>
我的解法:(1.Integer.toBinaryString(num)--将十进制数字转为二进制字符串; 2.str.toCharArray()--将字符串转为字符数组;)
1 public class Solution { 2 /** 3 * @param num: an integer 4 * @return: an integer, the number of ones in num 5 */ 6 public int countOnes(int num) { 7 // write your code here 8 String str = Integer.toBinaryString(num); 9 char[] ch = str.toCharArray(); 10 int cnt = 0; 11 for (int i = 0; i < ch.length; i++) { 12 if (ch[i] == \'1\') cnt++; 13 } 14 return cnt; 15 } 16 };
解法2:(位运算;num-1的结果是最右边1(包括1)的后面所有数取反,其他不变。例如1100-1=1011,111-1=110;(num-1)&num的结果便是把最右边的1置零。)O(m)
1 public class Solution { 2 /** 3 * @param num: an integer 4 * @return: an integer, the number of ones in num 5 */ 6 public int countOnes(int num) { 7 // write your code here 8 int cnt = 0; 9 while (num != 0) { 10 num = num & (num - 1); 11 cnt++; 12 } 13 return cnt; 14 } 15 };
解法3:(位运算;num和1与: 最右为1则1,最右为0则0,只能判断最右位;num右移。1&1=1,1&0=0,0&0=0;带符号右移>>会把所有的位右移,正数补0,负数补1; 无符号右移>>>,所有位右移,第一位补零)O(n)
1 public class Solution { 2 /** 3 * @param num: an integer 4 * @return: an integer, the number of ones in num 5 */ 6 public int countOnes(int num) { 7 // write your code here 8 int cnt = 0; 9 while (num != 0) { 10 cnt += num & 1; 11 num = num >>> 1; 12 } 13 return cnt; 14 } 15 };
35. Reverse Linked List: http://www.lintcode.com/en/problem/reverse-linked-list/
反转链表:(四步:1.tmp保存下一节点; 2.head指向prev; 3.head移动; 4.prev移动)
(prev-head移动遍历 tmp先保存head.next, 然后变换prev和head的指针; prev初始化为null; 最后返回prev)
1 public class Solution { 2 /** 3 * @param head: The head of linked list. 4 * @return: The new head of reversed linked list. 5 */ 6 public ListNode reverse(ListNode head) { 7 // write your code here 8 ListNode prev = null; 9 while (head != null) { 10 ListNode tmp = head.next; 11 head.next = prev; 12 prev = head; 13 head = tmp; 14 } 15 return prev; 16 } 17 }
36.Reverse Linked Lis II: http://www.lintcode.com/en/problem/reverse-linked-list-ii/
反转链表II:(1-[2-3-4]-5; 1.首先把head移动到目标范围前一指针;2.然后left和right作为范围头指针;right继续移动到范围尾指针;prev记录right下一个数;3.循环(n-m+1)次;4.最后把head指向right;)
(四个指针 head-left-right-prev; 初始head指向前一个,prev指向后一个; for(n-m+1)反转 prev-left-tmp三个一组; 循环后head.next=right; 与反转链表I的区别只在于需要head记录头指针,right记录尾指针; I的perv指向后一个null, II的prev指向后一个right.next)(ps:也可以省略right指针,因为反转最后prev就指向范围的最后一个节点, 所以只要head.next=prev即可)
1 public class Solution { 2 public ListNode reverseBetween(ListNode head, int m, int n) { 3 ListNode dummy = new ListNode(0); 4 dummy.next = head; 5 head = dummy; 6 7 for (int i = 0; i < m - 1; i++) { 8 head = head.next; 9 } 10 ListNode left = head.next; 11 ListNode right = head.next; 12 for (int i = 0; i < n - m; i++) { 13 right = right.next; 14 } 15 ListNode prev = right.next; 16 for (int i = 0; i < n - m + 1; i++) { 17 ListNode tmp = left.next; 18 left.next = prev; 19 prev = left; 20 left = tmp; 21 } 22 head.next = right; 23 return dummy.next; 24 } 25 }
135.Find Minimum in Rotated Sorted Array:http://www.lintcode.com/en/problem/find-minimum-in-rotated-sorted-array/
寻找旋转排序数组中的最小值:(思想:找出第一个小于[lo]的值(lo非固定);)
([2, 0, 1]; while(lo<hi),1. 首先如果[lo]<[hi],则可返回;2.定义mid,如果[mid]>=[lo],lo=mid+1;3.否则hi=mid;)
(注意判断[mid]=[lo]的情况,此时mid-lo-2,hi-0;显然是移动lo指针)
(而对于另一种写法是找出第一个小于[hi]的值;1相同;2.定义mid,如果[mid]>[hi]lo=mid+1; 否则hi=mid;好像不存在[mid]=[hi]的情况,因为[mid]是偏左的)
(本题mid只能定义为偏左,不然似乎写不出来)
<Binary Search>(二分搜索情况变化太复杂 while(</<=/+1<), if(>)mid/mid+1,else-mid/mid-1?)
解法1:(区间长度为1; while(<),if(>=)mid+1, else-mid, return lo; 改while/if任何一个部分都会wrong)
1 public class Solution { 2 /** 3 * @param nums: a rotated sorted array 4 * @return: the minimum number in the array 5 */ 6 public int findMin(int[] nums) { 7 // write your code here 8 int lo = 0, hi = nums.length - 1; 9 while (lo < hi) { 10 if (nums[lo] < nums[hi]) return nums[lo]; 11 int mid = lo + (hi - lo) / 2; 12 if (nums[mid] >= nums[lo]) lo = mid + 1; 13 else hi = mid; 14 } 15 return nums[lo]; 16 } 17 }
解法2:(区间长度为2; while(+1<), 如果lo<hi, 说明没有rotate,直接返回lo;如果lo>=mid,搜索右区间;否则搜索左区间。对于区间长度为2的情况,不用mid+1/-1;最后再判断lo和hi的值即可)
(1.lo,hi; 2.while(+1<),if(<)return; 3.mid,if(>=)-mid,else-mid; 4.return Math.min)
1 public class Solution { 2 /** 3 * @param nums: a rotated sorted array 4 * @return: the minimum number in the array 5 */ 6 public int findMin(int[] nums) { 7 // write your code here 8 int lo = 0, hi = nums.length - 1; 9 while (lo + 1 < hi) { 10 if (nums[lo] < nums[hi]) return nums[lo]; 11 int mid = lo + (hi - lo) / 2; 12 if (nums[mid] >= nums[lo]) lo = mid; 13 else hi = mid; 14 } 15 return Math.min(nums[lo],nums[hi]); 16 } 17 }
73.Construct Binary Tree from Preorder and Inorder Traversal: http://www.lintcode.com/en/problem/construct-binary-tree-from-preorder-and-inorder-traversal/
根据前序遍历和中序遍历构造树:(TreeNode helper(in,pre,inS,inE,preS); 如果(pre>len||inS>inE)null; 找出in中位置;递归得出left,right)
解法1:<Recursive>(Pre[a/bde/cfg] In[dbe/a/fcg] Pre[0]是root,在In中找到a是In[3]那么In[3]左边是左子树,右边是右子树。Pre[1]是左子树的根节点,同样在In中找到b,左边是左子树,右边是右子树。)
(1.helper; 2.helper:in,pre,preS,inS,inE; 3.if(||)null,root,index; 4.for(inS,inE)-index; 5.helper;)
1 public class Solution { 2 /** 3 *@param preorder : A list of integers that preorder traversal of a tree 4 *@param inorder : A list of integers that inorder traversal of a tree 5 *@return : Root of a tree 6 */ 7 public TreeNode buildTree(int[] preorder, int[] inorder) { 8 // write your code here 9 return helper(preorder, inorder, 0, 0, inorder.length - 1); 10 } 11 public TreeNode helper(int[] pre, int[] in, int preStart, int inStart, int inEnd) { 12 if (preStart > pre.length || inStart > inEnd) return null; 13 TreeNode root = new TreeNode(pre[preStart]); 14 int index = 0; 15 for (int i = inStart; i <= inEnd; i++) { 16 if (in[i] == pre[preStart]) { 17 index = i; 18 break; 19 } 20 } 21 root.left = helper(pre, in, preStart + 1, inStart, index - 1); 22 root.right = helper(pre, in, preStart + index- inStart + 1, index + 1, inEnd); 23 return root; 24 } 25 }
改进:(HashMap保存index的值)
(todo)
类似:
106. Construct Binary Tree from Inorder and Postorder Traversal: https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
根据中序遍历和后序遍历构造树:(helper(in,post,inS,inE,postE); 如果(preE<0||inS>inE)null; 找出in中位置;递归;)
(helper参数: in, post, inS, inE, postE; 1.终止条件为(||) return null; 2.postEnd作为new root; 3.在inS到inE之间遍历出root的位置作为index; 4.递归)
(主要是搞清迭代的值的变化)
1 public class Solution { 2 public TreeNode buildTree(int[] inorder, int[] postorder) { 3 return helper(inorder, postorder, postorder.length - 1, 0, inorder.length - 1); 4 } 5 public TreeNode helper(int[] in, int[] post, int postEnd, int inStart, int inEnd) { 6 if (postEnd < 0 || inStart > inEnd) return null; 7 TreeNode root = new TreeNode(post[postEnd]); 8 int index = 0; 9 for (int i = inStart; i <= inEnd; i++) { 10 if (in[i] == post[postEnd]) { 11 index = i; 12 break; 13 } 14 } 15 root.left = helper(in, post, postEnd - inEnd + index - 1, inStart, index - 1); 16 root.right = helper(in, post, postEnd - 1, index + 1, inEnd); 17 return root; 18 } 19 }
40.Implement Queue by Two Stacks:http://www.lintcode.com/en/problem/implement-queue-by-two-stacks/
用栈实现队列:(1.push-push到stack1中;2.pop-当stack2为空时(if),把stack1中的数push到stack2中(while),返回pop; 3.top-同pop,最后返回peek)
解法:(注意的是,只有当stack2为空时才把stack1里的值push到stack2里在peek/pop, 否则直接peek或者pop)
1 public class Queue { 2 private Stack<Integer> stack1; 3 private Stack<Integer> stack2; 4 5 public Queue() { 6 // do initialization if necessary 7 stack1 = new Stack<Integer>(); 8 stack2 = new Stack<Integer>(); 9 } 10 11 public void push(int element) { 12 // write your code here 13 stack1.push(element); 14 } 15 16 public int pop() { 17 //以上是关于LintCode:剑指Offer的主要内容,如果未能解决你的问题,请参考以下文章剑指 Offer(第 2 版)完整题解笔记 & C++代码实现(LeetCode版)
剑指 Offer(第 2 版)完整题解笔记 & C++代码实现(LeetCode版)
LeetCode(剑指 Offer)- 14- I. 剪绳子
LeetCode(剑指 Offer)- 14- I. 剪绳子
剑指 Offer 45. 把数组排成最小的数 剑指 Offer 61. 扑克牌中的顺子 剑指 Offer 40. 最小的k个数