今天做到一道題是這樣的: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上做題之體會(二)