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上做题之体会(二)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章