1. 程式人生 > >leetcode刷題記錄(949、367、374)

leetcode刷題記錄(949、367、374)

2018.12.25 leetcode 刷題總結

題號:949

給定一個由 4 位數字組成的陣列,返回可以設定的符合 24 小時制的最大時間。
最小的 24 小時制時間是 00:00,而最大的是 23:59。從 00:00 (午夜)開始算起,過得越久,時間越大。
以長度為 5 的字串返回答案。如果不能確定有效時間,則返回空字串。

示例 1:
輸入:[1,2,3,4]
輸出:“23:41”
示例 2:
輸入:[5,5,5,5]
輸出:""
提示:
A.length == 4
0 <= A[i] <= 9

我的想法:

  1. 獲得所有合法的小時組合,並記錄它們在陣列中的位置
  2. 遍歷所有合法的小時數,獲得相應小時數最大合法的分鐘數,即陣列中去除組合成小時數的兩個數去組成最大的合法的分鐘數
  3. 在遍歷的時候找出最大合法的小時數+分鐘數的組合
  4. 所有數字的不滿足的結果或初始值都會被賦成 -1

對應程式:

// java
class Solution {
	public String largestTimeFromDigits(int[] A) {
		// 獲得所有合法的小時組合
		// hourMap<小時數,List<組成小時數的兩個數字的下標>>
		Map<Integer, List<Integer>
> hourMap = hourCombo(A); // 若不存在,返回空 if(hourMap.size() == 0) { return ""; } // 記錄最大的小時數 int maxHour = -1; // 記錄同小時數相對應的分鐘數 int maxMin = -1; // 遍歷所有合法的小時數 for(Integer hour : hourMap.keySet()) { List<Integer> list = hourMap.get(hour); // 獲得與小時數相對應的分鐘數 int minute = maxMinute
(A, list); // 若無合法的分鐘數,跳到下一個小時數 if(minute == -1) { continue; }else { // 找出最大的組合 // 注意,能進到這個else中說明小時+分鐘的組合都是合法的, // 因此,找出小時數最大的就是組合後時間最大的 if(hour > maxHour) { maxHour = hour; maxMin = minute; } } } // 若不存在,返回空 if(maxHour == -1 || maxMin == -1) { return ""; } // 轉換格式,將一位數的數字前面加0 String hourStr = String.valueOf(maxHour); if(maxHour < 10) { hourStr = "0" + hourStr; } String minuteStr = String.valueOf(maxMin); if(maxMin < 10) { minuteStr = "0" + minuteStr; } // 返回 小時:分鐘 return hourStr + ":" + minuteStr; } // 獲得最大的合法的分鐘數 // @param A:所給陣列 // @param list:組成小時數的兩個數的下標 private int maxMinute(int[] A, List<Integer> list) { boolean flag = true; int a = -1; int b = -1; // 拿到陣列中其餘兩個數,分別賦給a,b for(int i = 0 ;i < A.length; ++i) { if(i == list.get(0) || i == list.get(1)) { continue; } if(flag) { a = A[i]; flag = false; }else { b = A[i]; } } // 得到所有的分鐘數(2種) int ab = a * 10 + b; int ba = b * 10 + a; // 找出在[0,59]中最大的一個數並返回,不存在返回-1 int result = -1; if(ab >= 0 && ab <= 59) { if(ab > result) { result = ab; } } if(ba >= 0 && ba <= 59) { if(ba > result) { result = ba; } } return result; } // 獲得所有合法的小時數的組合,並記錄他們的下標位置 private Map<Integer, List<Integer>> hourCombo(int[] A) { Map<Integer, List<Integer>> map = new HashMap<>(); List<Integer> list = null; for(int i = 0; i < A.length; ++i) { for(int j = 0; j < A.length; ++j) { // 不能和自己做小時數 if(j == i) { continue; } // 計算所有可能的小時數 int num = A[i] * 10 + A[j]; // 將小時數限制在[0,23]之間 if(num >= 0 && num <= 23) { list = new ArrayList<>(); // 記錄下標 list.add(i); list.add(j); // 新增結果 map.put(num, list); } } } return map; } }

題號:367

給定一個正整數 num,編寫一個函式,如果 num 是一個完全平方數,則返回 True,否則返回 False。
說明:不要使用任何內建的庫函式,如 sqrt。

示例 1:
輸入:16
輸出:True
示例 2:
輸入:14
輸出:False

我的想法:

n的完全平方等於n項由1開始的奇數的和
e.g. 16 = 1 + 3 + 5 + 7

對應程式:

// java
class Solution {
    public boolean isPerfectSquare(int num) {
			int flag = 1;
	        while(num > 0) {
	        	num -= flag;
	        	flag += 2;
	        	
	        	if(num == 0) {
	        		return true;
	        	}
	        }
	        
			return false;
    }
}

這個辦法在所給數字非常大的時候會費時,提交記錄中執行用時0ms的解答中用的是一種縮小區間逐漸逼近答案的辦法,類似二分查詢法

程式:

// java
class Solution {
    public boolean isPerfectSquare(int num) {
        long temp=num/2+1;
        long start=0;
        long end=temp;
        while(start<=end){
            long mid=start+(end-start)/2;
            long result=mid*mid;
            if(result==num)
                return true;
            else if(result<num)
                start=mid+1;
            else
                end=mid-1;
        }
        return false;
    }
}

上面的程式中,初始區間選在[0,n/2+1]之間,可以保證任何數的平方根都落在此區間,因為 (n/2+1)2 - n = n2/4 + 1 一定是大於零的。

題號:374

我們正在玩一個猜數字遊戲。 遊戲規則如下:
我從 1 到 n 選擇一個數字。 你需要猜我選擇了哪個數字。
每次你猜錯了,我會告訴你這個數字是大了還是小了。
你呼叫一個預先定義好的介面 guess(int num),它會返回 3 個可能的結果(-1,1 或 0):
-1 : 我的數字比較小
1 : 我的數字比較大
0 : 恭喜!你猜對了

示例 :
輸入: n = 10, pick = 6
輸出: 6

我的想法:

二分查詢,縮小查詢區間,遞迴呼叫guess()函式

對應程式:

// java
/* The guess API is defined in the parent class GuessGame.
   @param num, your guess
   @return -1 if my number is lower, 1 if my number is higher, otherwise return 0
      int guess(int num); */

public class Solution extends GuessGame {
    public int guessNumber(int n) {
        return guessNumber(1, n);
    }
    // @param start:區間左端點
    // @param end: 區間右端點
    private int guessNumber(int start, int end) {
    	// 二分查詢,標誌位數字
    	// 不要直接寫成(start + end)/ 2,防止溢位
		int temp = start + (end - start)/2;
		// 得到查詢結果標誌
		int guessFlag = guess(temp);
		
		if(guessFlag == 0) {
			// 遞迴出口
			return temp;
		}else if(guessFlag < 0) {
			// 區間向左縮小
			return guessNumber(start, temp-1);
		}else {
			// 區間向右縮小
			return guessNumber(temp+1, end);
		}
	}
}