LeetCode上做題之體會(一)

今天做到一道題是這樣的:Ugly Number

Write a program to check whether a given number is an ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 6, 8 are ugly while 14 is not ugly since it includes another prime factor 7.
Note that 1 is typically treated as an ugly number.

可能是因爲本人的英語水平不過關,一開始都Get不到這道題想要表達什麼,最後想了挺久的纔想到,原來這就是一個小學生的題目,這個醜數字原來就是不是純(2,3,5)的倍數的數字就是了。害我想那麼久。
好了知道思路之後就簡單了,下面貼一下我的代碼:

    public boolean isUgly(int num) {
        if(num == 0) return false;
        while(num % 5 == 0) num /= 5;
        while(num % 3 == 0) num /= 3;
        while(num % 2 == 0) num /= 2;
        if(num == 1) return true;
        return false;
    }

好了,這題真的是沒什麼難的,重在理解好吧。
但是在這裏我要提一下,上面while中的順序是有一點道理的,這樣排下來要是給的num大的話,可以減少循環的次數。


一道簡單的合併有序鏈表的題目:Merge Two Sorted Lists

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.

先給一下我自己的代碼:

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode newl,temp;
        if(l2 == null) return l1;
        if(l1 == null) return l2;
        if(l1.val <= l2.val){
            temp = l1;
            l1 = l1.next;
        }
        else{
            temp = l2;
            l2 = l2.next;
        }
        newl = temp;
        while(l1 != null || l2 != null){
            if(l1 == null){
                temp.next = l2;
                break;
            }
            if(l2 == null){
                temp.next = l1;
                break;
            }
            if(l1.val <= l2.val){
                temp.next = l1;
                l1 = l1.next;
            }
            else{
                temp.next = l2;
                l2 = l2.next;
            }
            temp = temp.next;
        }
        return newl;
    }

我上面的做法是一般人都會想到的,其實我上面的代碼還可以再省去一個鏈表指針的。(這裏需要提醒大家的是,不要忘記提前判空喔,少了這個這個可是會報錯的。)
然而以下是很簡潔的代碼,這是一個遞歸的方法:

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    if (l1 == null) return l2;
    if (l2 == null) return l1;
    ListNode head = l1.val < l2.val ? l1 : l2;
    ListNode nonHead = l1.val < l2.val ? l2 : l1;
    head.next = mergeTwoLists(head.next, nonHead);
    return head;
}

這是另外一道合併有序數組的題目:Merge Sorted Array

Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.
Note:
You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. The number of elements initialized in nums1 and nums2 are m and n respectively.

我一開始想到的一下的辦法:

    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int t;
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(nums1[i] > nums2[j]){
                    t = nums1[i];
                    nums1[i] = nums2[j];
                    nums2[j] = t;
                }
            }
        }
        Arrays.sort(nums2);
        for(int i = m, j = 0; i < m + n; i++,j++){
            nums1[i] = nums2[j];
        }
    }

我的方法是從前面開始遍歷,這樣的方法在這道題中會顯得比較差,首先事件複雜度就大了。
所以下面給出一個從後面開始比較的方法,這樣的方法比較比上面的,在時間複雜度上就優化的好多。

public void merge(int[] nums1, int m, int[] nums2, int n) {
    int l = m+n-1;
    m--;
    n--;
    while (m >= 0 && n >= 0) {
        if (nums1[m] > nums2[n]) {
            nums1[l] = nums1[m];
            l--;
            m--;
        } else {
            nums1[l] = nums2[n];
            l--;
            n--;
        }
    }
    for (int i = 0; i <= n; i++) {
        nums1[i] = nums2[i];
    }
}

一段讓我很佩服的遞歸代碼:

題目:Swap Nodes in Pairs
內容:Given a linked list, swap every two adjacent nodes and return its head.
For example,
Given 1->2->3->4, you should return the list as 2->1->4->3.
要求:Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.(意思就是不要直接修改鏈表中的值)。

    public ListNode swapPairs(ListNode head) {
        if ((head == null)||(head.next == null))
            return head;
        ListNode n = head.next;
        head.next = swapPairs(head.next.next);
        n.next = head;
        return n;
    }

我當時要看懂這個遞歸花了好多時間,按照遞歸的定義一步一步拆出來才能理解,真心讓我佩服的一段代碼。

迴文數的一個很好算法:

原題目:Palindrome Number
 Determine whether an integer is a palindrome. Do this without extra space.

下面是個好方法:

    public boolean isPalindrome(int x) {
        if(x != 0 && x % 10 == 0) return false;
        int finhalf = 0;
        while(x >finhalf){
            finhalf = finhalf * 10 + x % 10;
            x /= 10;
        }
        return x == finhalf || x == finhalf / 10;
    }

本來按照正常的思路我們應該會把一個一個將對稱的數字進行比較,可是這個算法的思維比較“發散”直接將這個數分成兩半,另這兩半直接比較。這確實能省時間和不用額外的空間開銷。

LeetCode中裏面還有好多很有意思的遞歸,以後有看到會繼續在這裏分享。
本篇博文已經太長了,下一篇請看:LeetCode上做題之體會(二)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章