開始在LeetCode上刷題(1-9)

轉載請註明:http://blog.csdn.net/HEL_WOR/article/details/50534392

因爲兩週前,對繼續讀理論書有點抗拒,所以想找點可以直接動手做的事,後來就找到了LeetCode。
到目前在LeetCode上完成了前9道題。
比較考腦子,就算把功能完成了,但隨後LeetCode顯示的排名也會讓你想繼續想如何優化已經寫好的代碼,往往優化的結果就是把代碼又重新實現了一次,比較費時間,但還好比較有意思。
LeetCode的題有些我是用JAVA實現,有些是用C#實現的。
1.Two Sum
這裏寫圖片描述
這道題我最開始的實現很簡單,直接兩個for循環加一個判斷就能實現了。

    public int[] twoSum(int[] nums, int target) {
         for (int i = 0; i < nums.length; i++) 
         {
             //// find two numbers such that they ....
             for (int j = i + 1; j < nums.length; j++) 
             {
                 if (nums[i] + nums[j] == target) 
                 {
                     if (i < j)
                     {
                         //// your returned answers (both index1 and index2) are not zero-based.
                         return new int[] { i + 1, j + 1 };
                     }
                     else 
                     {
                         return new int[] { j + 1, i + 1 };
                     }
                 }
             }
         }

         //// targe not found 
         return new int[] { 0, 0 };
    }

一次跑通,但最後的跑分結果:
這裏寫圖片描述

所以換了一個實現方式。把兩個for循環的遍歷換成了字典保存nums[]的所有成員。
我們要做的是每次在字典裏查詢是否主鍵爲target-nums[i]。

import java.util.Hashtable;
import java.util.Map;

public class Solution {
   private Map<Integer, Integer> hashTable = new Hashtable<Integer, Integer>(); 
    public int[] twoSum(int[] nums, int target) {
    for(int i = 0; i < nums.length; i++)
    {
          hashTable.put(nums[i], i);
    }

    Integer index = new Integer(0);
    int indexInt = 0;
    for(int i = 0; i < nums.length; i++)
    {
        index = hashTable.get(new Integer(target - nums[i]));
        if(index != null && (int)index != i)
        {
            indexInt = (int)index;
            if(i > indexInt)
            {
                i ^= indexInt;
                indexInt ^= i;
                i ^= indexInt;
            }

            return new int[]{i + 1, indexInt + 1};
        }
    }

    return new int[]{0, 0};
    }
}

這樣實現後跑分爲40%,但還是不夠,後面再改進吧。

2.Add Two Numbers
這裏寫圖片描述

這道題一開始我就審錯題了。
由此帶來的結果是寫完的代碼對不上題目想要的邏輯。
又出現短節了。
事後好好想了下思維上出現的問題。
當A,B是遵循了The digits are stored in reverse orde。那麼結果也該遵循這個規則。同一種類型應該是遵循一種規則的,爲什麼我會把AB和C分割開來思考,他們本該是一條線的,是不是我又想當然了,思維又開始到處跳躍了。
這道題需要處理的是進位。
跑分90%。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode AddTwoNumbers(ListNode l1, ListNode l2) {
         return this.Calc(l1, l2, 0);
    }

       private ListNode Calc(ListNode l1, ListNode l2, int carry) 
        {
            if (l1 == null && l2 == null) 
            {
                return carry == 0 ? null : new ListNode(1);
            }

            if (l1 == null) 
            {
                l1 = new ListNode(0);
            }

            if (l2 == null) 
            {
                l2 = new ListNode(0);
            }

            int sum = l1.val + l2.val + carry;
            ListNode head = new ListNode(sum % 10);
            head.next = Calc(l1.next, l2.next, sum / 10);
            return head;
        }
}

3.Longest Substring Without Repeating Characters
這裏寫圖片描述

這道題的解決思路類似前後兩個指針prve,next,最開始prve,next都指向字符串第一個字符,然後每次next都移向下一個字符,而prev只在next所指向字符和prve指向字符相同時才後移,通過判斷next和prev之間的長度就可以得到最大未重複子串。
現在的問題是如何保存上次字符出現的位置。思路類似第一題裏的字典,但這裏,我們可以用數組來描述這個hash表,由於題目中可以出現的字符沒有做限制,那麼我們可以按照ASCII碼與每一個字符位置對應,作爲數組的索引,數組中的內容就是出現這個字符出現的位置。
跑分90%。

  public int lengthOfLongestSubstring(String s) {
        //// 上次出現的位置
         int[] exist = new int[256];
         int index = 0;
         int maxLength = 0;
         char[] arr = s.toCharArray();
         for(int i = 0; i < arr.length; i++)
         {
             if(exist[arr[i]] > index)
             {
                 index = arr[i] + 1;
             }

             if(i - index > maxLength)
             {
                 maxLength = i - index;
             }

             exist[arr[i]] = i;
         }

         //// 加上最後一次計算最大長度後再首次加入的字符數
         return maxLength;
    }

4.Median of Two Sorted Arrays
這裏寫圖片描述
這道題的實現,我繞了幾個彎,要想辦法用上兩個子數組都是已排序的條件,這樣的話用歸併排序很有優勢,但又要求是O(log(m+n))的時間複雜度,於是我用BST實現了整個排序,然後判斷奇偶求出中位數,但這樣的話我沒有用上兩個數組已排序的前提條件,把兩個數組都重新排了次序,這樣就浪費這個前提條件,查了下資料,很多實現都把這道題納入了求Kth值得範圍。如這裏求兩個有序數組的第k大值。兩者本質上是一樣的。
對於其實現,雖然跑出了結果,但我感覺還是沒吃透。
跑分40%,還要改進。

 private double findKth(int A[], int aBeg, int B[], int bBeg, int k)   
       {  
           if (A.length - aBeg < B.length - bBeg) 
                return findKth(B, bBeg, A, aBeg, k);  
            if (bBeg == B.length)  
                return A[aBeg + k - 1];  
            if (k == 1)  
                return Math.min(A[aBeg], B[bBeg]);  

            int pb = Math.min(k / 2, B.length - bBeg), pa = k - pb;  
            if (A[aBeg + pa - 1] > B[bBeg + pb - 1])  
                return findKth(A, aBeg, B, bBeg + pb, pa);  
            else if (A[aBeg + pa - 1] < B[bBeg + pb - 1])  
                return findKth(A, aBeg + pa, B, bBeg, pb);  
            else  
                return A[aBeg + pa - 1];  
       }

       public double findMedianSortedArrays(int A[], int B[]) 
       {  
           return (findKth(A, 0, B, 0, (A.length + B.length + 1) / 2) + findKth(A, 0, B, 0, (A.length + B.length + 2) / 2)) / 2.0;  
    }  

5.Longest Palindromic Substring
這裏寫圖片描述
這道題和第3題類似,只是那道題是找不重複,這裏是要找重複,思路是對於第i個字符,檢查i前一個和i後一個字符是否相等,相等則繼續擴張。
但這裏要區分abba和aba的情況。這樣的話一個指針就沒法解決這個問題了,那麼如果是兩個指針的話,i和j,比較i+1和j-1字符是否相等,這樣雖然還是會遇到只有一個指針時要遇到的情況,但卻不會錯過abba的情況了。
保存是否兩個位置上的字符是否相等,仍可以用數組來完成,第i個字符和第j個字符對於二維數組ij。用布爾類型來描述是否相等。
雖然實現了,但是最後的跑分,慘不忍睹。代碼裏的打標記過程就花費了n^2的複雜度。

 public String longestPalindrome(String s) {
      char[] arr = s.toCharArray();
        boolean[][] flag = new boolean[arr.length][arr.length];
        int maxLength = 0;
        int index = 0;
        for(int i = 0; i < arr.length; i++)
        {
            for(int j = 0; j < arr.length; j++)
            {
                if(arr[i] == arr[j])
                {
                    flag[i][j] = true;
                }
            }
        }

        for(int j = 1; j < arr.length; j++)
        {
            for(int i = 0; i < j; i++)
            {
                if(arr[i] == arr[j] && flag[i + 1][j - 1])
                {
                    if(j - i > maxLength)
                    {
                        index = i;
                        maxLength = j - i;
                    }
                }
                else
                {
                    flag[i][j] = false;
                }
            }
        }

        return s.substring(index, index + maxLength + 1);
    }

6.ZigZag Conversion
這裏寫圖片描述

這道題的目的是要你將字符串的每個字符排列成鋸齒形狀再按每一行依次輸出。先考慮如何弄成鋸齒形狀。
這裏寫圖片描述
如果要弄成鋸齒狀輸出,那麼控制下Console.WriteLine()和Console.Write()的時機就可以完成,但這裏是要求打印鋸齒狀後的每一行。
以行數爲5爲例,觀察上面鋸齒的產生過程,對於斜行,其都是夾在相鄰兩行起點和終點之間的,那麼斜行的元素個數必然會少2。即斜行的元素個數都是行數rows-2。這個因素定下來了,後面的就不會順序就不會有改變了。
跑分90%。

  public string Convert(string s, int numRows) {
        if (numRows == 1) 
            {
                return s;
            }

        char[] arr = s.ToCharArray();
        StringBuilder result = new StringBuilder();
        StringBuilder[] str = new StringBuilder[numRows];
        for (int i = 0; i < str.Length; i++)
        {
            str[i] = new StringBuilder();
        }

        int index = 0;
        int j = 0;
        while (index < arr.Length) 
        {
            for (j = 0; index < arr.Length && j < numRows; index++) 
            {
                str[j++].Append(arr[index]);
            }

            for (j = numRows - 2; index < arr.Length && j > 0; ) 
            {
                str[j--].Append(arr[index++]);
            }
        }

        for(int i = 0; i < str.Length; i++)
        {
            result.Append(str[i].ToString());
        }

        return result.ToString();
    }

7.Reverse Integer
這裏寫圖片描述

能用%,/運算符分割出每一位就別用轉換成字符串來描述。能用每次取個位後乘10升位來反轉就別用字符串來對字符做交換。
做超限處理。
注意int的表示範圍。
跑分30%。低。。

 public int Reverse(int x) {
        Int64 result = 0;
        while (x != 0)
        {
            int i = x % 10;
            result = result * 10 + i;
            if (result > Int32.MaxValue || result < Int32.MinValue) 
            {
                result = 0;
                break;
            }

            x /= 10;
        }

        return (int)result;
    }

8.String to Integer (atoi)
這裏寫圖片描述

這道題提交了很多次,題沒審清,英文描述沒去細細讀。
int超界是個頭疼的事情,用Int64來裝都被一個測試用例超界反轉了。
最後跑分已慘不忍睹。還得改。

 public int MyAtoi(string str) {
      str = str.Trim();
            if (string.IsNullOrEmpty(str)) 
            {
                return 0;
            }

            char[] arr = str.ToCharArray();
            Int64 result = 0;
            int bit = 0;
            bool negative = false;
            if (!(arr[0] == 43 || arr[0] == 45 || arr[0] > 47 && arr[0] < 58))
            {
                return 0;
            }

            if (arr[0] == 43 || arr[0] == 45) 
            {
                if (arr.Length == 1 || !(arr[1] > 47 && arr[1] < 58)) 
                {
                    return 0;
                }
            }

            if (arr[0] == 45) 
            {
                negative = true;
            }

            for (int i = 0; i < arr.Length; i++) 
            {
                if (arr[i] > 47 && arr[i] < 58)
                {
                    bit++;
                    result = result * 10 + int.Parse(arr[i].ToString());
                    if (i < arr.Length - 1) 
                    {
                        if (arr[i + 1] <= 47 || arr[i + 1] >= 58)
                        {
                            break;
                        }
                    }
                }
            }

            if (negative)
            {
                result *= -1;
            }

            if (bit > 10 || result > Int32.MaxValue || result < Int32.MinValue)
            {
                result = negative ? Int32.MinValue : Int32.MaxValue;
            }

            return (int)result;
    }

9.Palindrome Number
這裏寫圖片描述

相對於第5題求最長迴文子串,這道題就簡單很多了,因爲開始結束位置都是確定了的。
跑分60%。

    public bool IsPalindrome(int x) {
        //// -109 和 901-纔是迴文
        if (x < 0) 
        {
            return false;
        }

        int ori = x;
        int res = 0;
        while (ori > 0) 
        {
            res = res * 10 + ori % 10;
            ori /= 10;
        }

        return res == x;
    }

1-9道算法題的記錄到這裏就完成了。後面再繼續了。

發佈了31 篇原創文章 · 獲贊 11 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章