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 }
View Code

解法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 }
View Code

 


 

第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 }
View Code

 

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 };
View Code

 

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 }
View Code
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;
    }
}
View Code

 

 

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 };
View Code

解法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 };
View Code

解法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 };
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

解法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 }
View Code

 

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 }
View Code

改进:(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 }
View Code

 

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——第二十九天(动态规划“困难”)

剑指 Offer 45. 把数组排成最小的数 剑指 Offer 61. 扑克牌中的顺子 剑指 Offer 40. 最小的k个数