LintCode算法刷題記錄(入門 + 簡單部分)

由於是初學者,實現的方法都很簡單,暫時不考慮效率,之後(可能)會更新

1. A+B問題

給出兩個整數 aa 和 bb , 求他們的和。

樣例

如果 a=1 並且 b=2,返回3。

挑戰

顯然你可以直接 return a + b,但是你是否可以挑戰一下不這樣做?(不使用++等算數運算符)

說明

a和b都是 32位 整數麼?
是的
我可以使用位運算符麼?
當然可以

注意事項

你不需要從輸入流讀入數據,只需要根據aplusb的兩個參數a和b,計算他們的和並返回就行。

思路

考慮進位即可

public class Solution {
    /**
     * @param a: An integer
     * @param b: An integer
     * @return: The sum of a and b 
     */
    public int aplusb(int a, int b) {
        // write your code here
        if (a == 0){return b;}
        if (b == 0){return a;}
        int sum, add;
        sum = a ^ b;
        add = (a & b) << 1;
        return aplusb(add,sum);
    }
}

2. 尾部的零

設計一個算法,計算出n階乘中尾部零的個數

樣例

11! = 39916800,因此應該返回 2

挑戰

O(logN)的時間複雜度

思路

思路參考內容

public class Solution {
    /*
     * @param n: An integer
     * @return: An integer, denote the number of trailing zeros in n!
     */
    public long trailingZeros(long n) {
        // write your code here, try to do it without arithmetic operators.
        long count = 0L;
        while(n > 0){
            count = (long) (count + (Math.floor(n / 5)));
            n = (long) Math.floor(n / 5);
        }
        return count;
    }
}

6. 合併排序數組 II

合併兩個排序的整數數組A和B變成一個新的數組。

樣例

給出A=[1,2,3,4],B=[2,4,5,6],返回 [1,2,2,3,4,4,5,6]

挑戰

你能否優化你的算法,如果其中一個數組很大而另一個數組很小?

思路

兩個指針,每次比較兩個數組指針指向元素的大小,小的元素加入新數組,指針後移一位,直到一個數組指針到末尾,另一個數組全部加入新數組。

public class Solution {
    /**
     * @param A: sorted integer array A
     * @param B: sorted integer array B
     * @return: A new sorted integer array
     */
    public int[] mergeSortedArray(int[] A, int[] B) {
        // write your code here
       int i = 0;
       int j = 0;
       List<Integer> result = new ArrayList<Integer>();
       while(true){
           if(i < A.length && j < B.length){
               if(A[i] < B[j]){
                   result.add(A[i]);
                   i++;
               }else{
                   result.add(B[j]);
                   j++;
               }
           }else{
               if (i == A.length){
                   for(int m = j;m < B.length;m++){
                        result.add(B[m]);
                   }
                   break;
               }else{
                   for(int n = i;n < A.length;n++){
                        result.add(A[n]);
                   }
                    break;
               }
           }
       }
       int[] re = new int[result.size()];
       for(int k = 0;k < result.size();k++){
           re[k] = result.get(k);
       }
       return re;
    }
}

8. 旋轉字符串

給定一個字符串和一個偏移量,根據偏移量旋轉字符串(從左向右旋轉)

樣例

對於字符串 “abcdefg”.

offset=0 => “abcdefg”
offset=1 => “gabcdef”
offset=2 => “fgabcde”
offset=3 => “efgabcd”

挑戰

在數組上原地旋轉,使用O(1)的額外空間

思路

循環取出末尾元素,其餘元素前移一位,取出元素置於首位。(注意數組爲空的情況)

public class Solution {
    /**
     * @param str: An array of char
     * @param offset: An integer
     * @return: nothing
     */
    public void rotateString(char[] str, int offset) {
        // write your code here
        if (str.length != 0){
            char temp = 'a';
            int l = str.length - 1;
            int L = str.length;
            if (offset > L){
                int n = offset / L;
                offset -= n * L;
            }
            while (offset > 0){
                offset--;
                temp = str[l];
                for(int i = 0;i < l;i++){
                    str[l - i] = str[l - i - 1];
                }
                str[0] = temp;
            } 
        }       
    }
}

9. Fizz Buzz 問題

給你一個整數n. 從 1 到 n 按照下面的規則打印每個數:
如果這個數被3整除,打印fizz.
如果這個數被5整除,打印buzz.
如果這個數能同時被3和5整除,打印fizz buzz.

樣例

比如 n = 15, 返回一個字符串數組:
[
“1”, “2”, “fizz”,
“4”, “buzz”, “fizz”,
“7”, “8”, “fizz”,
“buzz”, “11”, “fizz”,
“13”, “14”, “fizz buzz”
]

挑戰

Can you do it with only one if statement?
挑戰參考思路1

思路

依次判斷即可

public class Solution {
    /**
     * @param n: An integer
     * @return: A list of strings.
     */
    public List<String> fizzBuzz(int n) {
        // write your code here
       List<String> result = new ArrayList<String>();
       for(int i = 1;i <= n;i++){
           if (i % 3 == 0){
               if (i % 5 == 0){
                   result.add("fizz buzz");
               }else{
                   result.add("fizz");
               }
           }else{
               if (i % 5 == 0){
                   result.add("buzz");
               }else{
                   result.add(""+i);
               }
           }
       }
       return result;
    }
} 

13. 字符串查找

對於一個給定的 source 字符串和一個 target 字符串,你應該在 source 字符串中找出 target 字符串出現的第一個位置(從0開始)。如果不存在,則返回 -1。

樣例

如果 source = “source” 和 target = “target”,返回 -1。
如果 source = “abcdabcdefg” 和 target = “bcd”,返回 1。

挑戰

O(n2)的算法是可以接受的。如果你能用O(n)的算法做出來那更加好。(提示:KMP)

說明

在面試中我是否需要實現KMP算法?

不需要,當這種問題出現在面試中時,面試官很可能只是想要測試一下你的基礎應用能力。當然你需要先跟面試官確認清楚要怎麼實現這個題。

思路

不考慮KMP算法,當每個主串和匹配串首元素相同的時候匹配剩餘字符,不匹配則回到原位置繼續尋找下一個首元素匹配的位置,直到找到,否則返回-1.(注意當主串剩餘長度不足匹配串長度,直接返回-1,否則超出索引報錯)

public class Solution {
    /**
     * @param source: 
     * @param target: 
     * @return: return the index
     */
    public int strStr(String source, String target) {
        // Write your code here
        if(target.equals("")){
            return 0;
        }else if(source.equals("")){
            return -1;
        }
        int targetLength = target.length();
        int i = 0;
        while(i < source.length()){
            if (source.charAt(i) == target.charAt(0)){
                for(int j = 0;j < targetLength;j++){
                    if (i + j == source.length()){
                        return -1;
                    }
                    if (target.charAt(j) != source.charAt(i+j)){
                        break;
                    }else{
                        if (j == targetLength - 1){
                            return i;
                        }
                    }
                }
            }
            i++;   
        }
        return -1;
    }
}

14. 二分查找

給定一個排序的整數數組(升序)和一個要查找的整數target,用O(logn)的時間查找到target第一次出現的下標(從0開始),如果target不存在於數組中,返回-1。

樣例

在數組 [1, 2, 3, 3, 4, 5, 10] 中二分查找3,返回2。

挑戰

如果數組中的整數個數超過了2^32,你的算法是否會出錯?

思路

經典的二分查找即可,注意由於數組有重複項,查到之後要向前遍歷,找到第一個匹配的元素,網上很多方法沒有考慮這個。

public class Solution {
    /**
     * @param nums: The integer array.
     * @param target: Target to find.
     * @return: The first position of target. Position starts from 0.
     */
    public int binarySearch(int[] nums, int target) {
        // write your code here
        int begin = 0;
        int end = nums.length - 1;
        int temp = 0;
        if (target == nums[begin]){
            return begin;
        }
        if (target == nums[end]){
            return end;
        }
        if (end - begin < 2){
            return -1;
        }else{
            while(true){
                temp = end;
                end = (begin + end) / 2;
                if(end == begin){
                    return -1;
                }
                if(target == nums[end]){
                    while(true){
                        if (nums[end - 1] == nums[end]){
                            end--;
                        }else{
                            return end;
                        }
                    }
                }else if (nums[end] < target){
                    begin = end;
                    end = temp;
                }
            }
        }
    }
}

22. 平面列表

給定一個列表,該列表中的每個要素要麼是個列表,要麼是整數。將其變成一個只包含整數的簡單列表。

樣例

給定 [1,2,[1,2]],返回 [1,2,1,2]。
給定 [4,[3,[2,[1]]]],返回 [4,3,2,1]。

挑戰

請用非遞歸方法嘗試解答這道題。

注意事項

如果給定的列表中的要素本身也是一個列表,那麼它也可以包含列表。

思路

遞歸對每個元素進行判斷,用好題目所給的接口。

/**
 * // This is the interface that allows for creating nested lists.
 * // You should not implement it, or speculate about its implementation
 * public interface NestedInteger {
 *
 *     // @return true if this NestedInteger holds a single integer,
 *     // rather than a nested list.
 *     public boolean isInteger();
 *
 *     // @return the single integer that this NestedInteger holds,
 *     // if it holds a single integer
 *     // Return null if this NestedInteger holds a nested list
 *     public Integer getInteger();
 *
 *     // @return the nested list that this NestedInteger holds,
 *     // if it holds a nested list
 *     // Return null if this NestedInteger holds a single integer
 *     public List<NestedInteger> getList();
 * }
 */
public class Solution {
    private List<Integer> result = new ArrayList<Integer>();
    // @param nestedList a list of NestedInteger
    // @return a list of integer
    public List<Integer> flatten(List<NestedInteger> nestedList) {
        // Write your code here
        for(int i = 0;i < nestedList.size();i++){
            if(nestedList.get(i).isInteger()){
                result.add(nestedList.get(i).getInteger());
            }else{
                flatten(nestedList.get(i).getList());
            }
        }
        return result;
    }
}

28. 搜索二維矩陣

寫出一個高效的算法來搜索 m × n矩陣中的值。
這個矩陣具有以下特性:
每行中的整數從左到右是排序的。
每行的第一個數大於上一行的最後一個整數。

樣例

考慮下列矩陣:
[
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
給出 target = 3,返回 true

挑戰

O(log(n) + log(m)) 時間複雜度

思路

因爲矩陣是排好序的,所有通過比對每行第一個數據可以確定目標值所在的行,然後遍歷該行即可

public class Solution {
    /**
     * @param matrix: matrix, a list of lists of integers
     * @param target: An integer
     * @return: a boolean, indicate whether matrix contains target
     */
    public boolean searchMatrix(int[][] matrix, int target) {
        // write your code here
        int m = matrix.length;
        if(m == 0){
            return false;
        }
        int n = matrix[m - 1].length;
        if(n == 0){
            return false;
        }
        if (target < matrix[0][0] || target > matrix[m - 1][n - 1]){
            return false;
        }else{
            int i = 0;
            while(i < m && target >= matrix[i][0]){
                if(target == matrix[i][0]){
                return true;
                }
                i++;
            }
            i--;
            for(int j = 0;j < matrix[i].length;j++){
                if(matrix[i][j] == target){
                    return true;
                }
            }
        }
        return false;
    }
}

35. 翻轉鏈表

翻轉一個鏈表

樣例

給出一個鏈表1->2->3->null,這個翻轉後的鏈表爲3->2->1->null

挑戰

在原地一次翻轉完成

思路

遍歷鏈表將所有值取出存在list裏,然後將list值倒序賦值給鏈表的節點

/**
 * Definition for ListNode
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */

public class Solution {
    /**
     * @param head: n
     * @return: The new head of reversed linked list.
     */
    public ListNode reverse(ListNode head) {
        // write your code here
        if (head == null){
            return null;
        }
        ListNode currentNode = head;
        List<Integer> tempList = new ArrayList<Integer>();
        while(currentNode != null){
            tempList.add(currentNode.val);
            currentNode = currentNode.next;
        }
        currentNode = head;
        int tempListSize = tempList.size();
        for(int i = 0;i < tempListSize;i++){
            currentNode.val = tempList.get(tempListSize - 1 -i);
            currentNode = currentNode.next;
        }
        return head;
    }
}

37. 反轉一個3位整數

反轉一個只有3位數的整數。

樣例

123 反轉之後是 321。
900 反轉之後是 9。

注意事項

你可以假設輸入一定是一個只有三位數的整數,這個整數大於等於100,小於1000。

思路

將每一位依次取出即可

public class Solution {
    /**
     * @param number: A 3-digit number.
     * @return: Reversed number.
     */
    public int reverseInteger(int number) {
        // write your code here
        int a = number / 100;
        int b = (number - a * 100 ) / 10;
        int c = number - a * 100 - b * 10;
        String re_num = "";
        re_num = "" + c + b + a ;
        int result = Integer.parseInt(re_num);
        return result;
    }
}

39. 恢復旋轉排序數組

這道題的評判系統有bug,沒有設置[1,1,1,1,1]此類數據,導致代碼可能陷入死循環卻不自知
給定一個旋轉排序數組,在原地恢復其排序。

樣例

[4, 5, 1, 2, 3] -> [1, 2, 3, 4, 5]

挑戰

使用O(1)的額外空間和O(n)時間複雜度

說明

什麼是旋轉數組?

比如,原始數組爲[1,2,3,4], 則其旋轉數組可以是[1,2,3,4], [2,3,4,1], [3,4,1,2], [4,1,2,3]

思路

每次判斷首位元素是否小於等於第二位元素,如果是,則取出放到末尾。也可以判斷首位元素是否大於等於末位元素,如果是,則取出首位放到末位。注意空數組的特殊情況即可。另外注意[1,1,1,1,1]這種所有元素相等的情況,以下代碼加入計數器,當計數器大於數組長度即說明所有元素均相等,退出循環。

public class Solution {
    /**
     * @param nums: An integer array
     * @return: nothing
     */
    public void recoverRotatedSortedArray(List<Integer> nums) {
        // write your code here
        int numsSize = nums.size();
        if(numsSize > 0 && nums.get(0) >= nums.get(numsSize - 1)){
            int temp = 0;
            int count = 0;
            while(true){
                if(count > numsSize){
                    break;
                }
                if(nums.get(0) <= nums.get(1)){
                    temp = nums.get(0);
                    nums.remove(0);
                    nums.add(temp);
                    count++;
                }else{
                    temp = nums.get(0);
                    nums.remove(0);
                    nums.add(temp);
                    break;
                }
            }
        }
    }
}

41. 最大子數組

給定一個整數數組,找到一個具有最大和的子數組,返回其最大和。

樣例

給出數組[−2,2,−3,4,−1,2,1,−5,3],符合要求的子數組爲[4,−1,2,1],其最大和爲6

挑戰

要求時間複雜度爲O(n)

注意事項

子數組最少包含一個數

思路

不考慮時間複雜度,雙層循環,每次從nums[i]開始,一個一個累加,遇到比max大的就賦給max,直到循環結束。
這個題網上很多答案說單層循環,遇到和小於0直接捨棄,但是數組如果所有元素都小於0呢???
補充:由於是先與max比較再捨棄,所以沒有問題

public class Solution {
    /**
     * @param nums: A list of integers
     * @return: A integer indicate the sum of max subarray
     */
    public int maxSubArray(int[] nums) {
        // write your code here
        int sum;
        int max = nums[0];
        for(int i = 0;i < nums.length;i++){
            sum = 0;
            for(int j = 0;j < nums.length - i;j++){
                sum = sum + nums[i + j];
                if (sum > max){
                    max = sum;
                }
            }
        }
        return max;
    }
}

44. 最小子數組

給定一個整數數組,找到一個具有最小和的子數組。返回其最小和。

樣例

給出數組[1, -1, -2, 1],返回 -3

注意事項

子數組最少包含一個數字

思路

與41題一樣,大於號和小於號換一下就行,此處貼出其他人的代碼,原地址:參考代碼

public class Solution {
    /*
     * @param nums: a list of integers
     * @return: A integer indicate the sum of minimum subarray
     */
    public int minSubArray(List<Integer> A) {
        // write your code here
        int min = Integer.MAX_VALUE, sum = 0;
        for (int i = 0; i < A.size(); i++) {
            sum += A.get(i);
            min = Math.min(min, sum);
            sum = Math.min(sum, 0);
        }
        return min;
    }
}

145. 大小寫轉換

將一個字符由小寫字母轉換爲大寫字母

樣例

a -> A
b -> B

思路

根據ascii碼,減去32即可

public class Solution {
    /**
     * @param character: a character
     * @return: a character
     */
    public char lowercaseToUppercase(char character) {
        // write your code here
        return (char)((int) character - 32);
    }
}

454. 矩陣面積

實現一個矩陣類Rectangle,包含如下的一些成員變量與函數:
兩個共有的成員變量 width 和 height 分別代表寬度和高度。
一個構造函數,接受2個參數 width 和 height 來設定矩陣的寬度和高度。
一個成員函數 getArea,返回這個矩陣的面積。

樣例

Example1:
Java:
Rectangle rec = new Rectangle(3, 4);
rec.getArea(); // should get 12,3*4=12

Python:
rec = Rectangle(3, 4)
rec.getArea()

Example2:
Java:
Rectangle rec = new Rectangle(4, 4);
rec.getArea(); // should get 16,4*4=16

Python:
rec = Rectangle(4, 4)
rec.getArea()

思路

參考各語言教程

public class Rectangle {
    /*
     * Define two public attributes width and height of type int.
     */
    // write your code here
    private int width;
    private int height;
    /*
     * Define a constructor which expects two parameters width and height here.
     */
    // write your code here
    public Rectangle(int width,int height){
        this.width = width;
        this.height = height;
    }
    /*
     * Define a public method `getArea` which can calculate the area of the
     * rectangle and return.
     */
    // write your code here
    public int getArea(){
        return this.width * this.height;
    }
}

463. 整數排序

給一組整數,按照升序排序,使用選擇排序,冒泡排序,插入排序或者任何 O(n2) 的排序算法。

樣例

對於數組 [3, 2, 1, 4, 5], 排序後爲:[1, 2, 3, 4, 5]。

思路

冒泡排序

public class Solution {
    /**
     * @param A: an integer array
     * @return: nothing
     */
    public void sortIntegers(int[] A) {
        // write your code here
        int temp;
        for(int i = 0;i < A.length;i++){
            for(int j = i + 1;j < A.length;j++)
            {
                if (A[j] < A[i]){
                    temp = A[j];
                    A[j] = A[i];
                    A[i] = temp;
                }
            }
        }
    }
}

466. 鏈表節點計數

計算鏈表中有多少個節點.

樣例

給出 1->3->5, 返回 3.

思路

從head開始依次計數,直到next爲null

/**
 * Definition for ListNode
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */

public class Solution {
    /**
     * @param head: the first node of linked list.
     * @return: An integer
     */
    public int countNodes(ListNode head) {
        // write your code here
        if(head == null){
            return 0;
        }
        ListNode p = head;
        ListNode q = head.next;
        int count = 1;
        while(q!=null){
            count++;
            p = q;
            q = p.next;
        }
        return count;
    }
}

484. 交換數組兩個元素

略。

632. 二叉樹的最大節點

在二叉樹中尋找值最大的節點並返回。

樣例

給出如下一棵二叉樹:

     1
   /   \
 -5     3
 / \   /  \
1   2 -4  -5 

返回值爲 3 的節點。

思路

中序遍歷二叉樹,將二叉樹節點的值存入鏈表

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */
public class Solution {
    /*
     * @param root: the root of tree
     * @return: the max node
     */
    public TreeNode maxNode(TreeNode root) {
        // Write your code here
        TreeNode resultMaxNode = root;
        TreeNode currentNode = root;
        LinkedList<TreeNode> nodeLink = new LinkedList<TreeNode>();
        while(currentNode != null || !nodeLink.isEmpty()){
            if(currentNode != null){
                nodeLink.push(currentNode);
                currentNode = currentNode.left;
            }else{
                currentNode = nodeLink.pop();
                if(currentNode.val > resultMaxNode.val){
                    resultMaxNode = currentNode;
                }
                currentNode = currentNode.right;
            }
        }
        return resultMaxNode;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章