日期之間隔幾天
請你編寫一個程序來計算兩個日期之間隔了多少天。
日期以字符串形式給出,格式爲 YYYY-MM-DD,如示例所示。
示例 1:
輸入:date1 = “2019-06-29”, date2 = “2019-06-30”
輸出:1
示例 2:
輸入:date1 = “2020-01-15”, date2 = “2019-12-31”
輸出:15
提示:
給定的日期是 1971 年到 2100 年之間的有效日期。
思路
超級經典的模擬題。關鍵在於提取公共部分寫成函數,不要讓思維淹沒在for-if-else
的海洋裏。
代碼
class Solution {
private static final int[] Months = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
private boolean runNian(int year) {
if (year % 400 == 0) {
return true;
}
if (year % 100 == 0) {
return false;
}
if (year % 4 == 0) {
return true;
} else {
return false;
}
}
private int fromYearBegin(int year, int month, int day) {
int i = 0, ret = 0;
for (i=0; i<month-1; ++i) {
ret += (i==1 && runNian(year))? Months[i] + 1: Months[i];
}
return ret + day;
}
public int daysBetweenDates(String date1, String date2) {
int i = 0, ret = 0;
if (date1.compareTo(date2) < 0) {
String tmp = date1;
date1 = date2;
date2 = tmp;
}
String[] fields = date1.split("-");
int y1 = Integer.parseInt(fields[0]), m1 = Integer.parseInt(fields[1]), d1 = Integer.parseInt(fields[2]);
fields = date2.split("-");
int y2 = Integer.parseInt(fields[0]), m2 = Integer.parseInt(fields[1]), d2 = Integer.parseInt(fields[2]);
for (i=y2; i<y1; ++i) {
ret += runNian(i)? 366: 365;
}
ret += fromYearBegin(y1, m1, d1) - fromYearBegin(y2, m2, d2);
return ret;
}
}
驗證二叉樹
二叉樹上有 n 個節點,按從 0 到 n - 1 編號,其中節點 i 的兩個子節點分別是 leftChild[i] 和 rightChild[i]。
只有 所有 節點能夠形成且 只 形成 一顆 有效的二叉樹時,返回 true;否則返回 false。
如果節點 i 沒有左子節點,那麼 leftChild[i] 就等於 -1。右子節點也符合該規則。
注意:節點沒有值,本問題中僅僅使用節點編號。
示例 1:
輸入:n = 4, leftChild = [1,-1,3,-1], rightChild = [2,-1,-1,-1]
輸出:true
示例 2:
輸入:n = 4, leftChild = [1,-1,3,-1], rightChild = [2,3,-1,-1]
輸出:false
示例 3:
輸入:n = 2, leftChild = [1,0], rightChild = [-1,-1]
輸出:false
示例 4:
輸入:n = 6, leftChild = [1,-1,-1,4,-1,-1], rightChild = [2,-1,-1,5,-1,-1]
輸出:false
提示:
1 <= n <= 10^4
leftChild.length == rightChild.length == n
-1 <= leftChild[i], rightChild[i] <= n - 1
思路
按照『樹』的定義,遞歸判斷是否有環以及是否連通
代碼
class Solution {
private int dfs(int s, boolean[] vis, int[] left, int[] right) {
vis[s] = true;
int ret = 1;
if (left[s] != -1) {
if (vis[left[s]]) {
return -1;
}
ret += dfs(left[s], vis, left, right);
}
if (right[s] != -1) {
if (vis[right[s]]) {
return -1;
}
ret += dfs(right[s], vis, left, right);
}
return ret;
}
public boolean validateBinaryTreeNodes(int n, int[] leftChild, int[] rightChild) {
boolean[] vis = new boolean[n];
return dfs(0, vis, leftChild, rightChild) == n;
}
}
最接近的因數
給你一個整數 num,請你找出同時滿足下面全部要求的兩個整數:
兩數乘積等於 num + 1 或 num + 2
以絕對差進行度量,兩數大小最接近
你可以按任意順序返回這兩個整數。
示例 1:
輸入:num = 8
輸出:[3,3]
解釋:對於 num + 1 = 9,最接近的兩個因數是 3 & 3;對於 num + 2 = 10, 最接近的兩個因數是 2 & 5,因此返回 3 & 3 。
示例 2:
輸入:num = 123
輸出:[5,25]
示例 3:
輸入:num = 999
輸出:[40,25]
提示:
1 <= num <= 10^9
代碼
class Solution {
private int[] divide(int num) {
int[] ret = new int[2];
for (int i=(int)Math.sqrt(num); i>=1; --i) {
if (num % i == 0) {
ret[0] = i;
ret[1] = num / i;
break;
}
}
return ret;
}
public int[] closestDivisors(int num) {
int[] div1 = divide(num + 1), div2 = divide(num + 2);
if (Math.abs(div1[0] - div1[1]) < Math.abs(div2[0] - div2[1])) {
return div1;
} else {
return div2;
}
}
}
形成三的最大倍數
給你一個整數數組 digits,你可以通過按任意順序連接其中某些數字來形成 3 的倍數,請你返回所能得到的最大的 3 的倍數。
由於答案可能不在整數數據類型範圍內,請以字符串形式返回答案。
如果無法得到答案,請返回一個空字符串。
示例 1:
輸入:digits = [8,1,9]
輸出:“981”
示例 2:
輸入:digits = [8,6,7,1,0]
輸出:“8760”
示例 3:
輸入:digits = [1]
輸出:""
示例 4:
輸入:digits = [0,0,0,0,0,0]
輸出:“0”
提示:
1 <= digits.length <= 10^4
0 <= digits[i] <= 9
返回的結果不應包含不必要的前導零。
思路
注意到3的倍數的特點是各位相加也是3的倍數。另外注意去掉前導零。
代碼
class Solution {
private String toZero(String num) {
if (num.length() > 0 && num.charAt(0) == '0') {
return "0";
} else {
return num;
}
}
public String largestMultipleOfThree(int[] digits) {
if (digits.length == 0) {
return "";
}
int sum = 0, n = digits.length, i = 0;
StringBuilder sb = new StringBuilder();
Arrays.sort(digits);
for (int dig: digits) {
sum += dig;
}
if (sum % 3 == 0) {
for (i=n-1; i>=0; --i) {
sb.append(digits[i]);
}
return toZero(sb.toString());
}
int minMod1 = Integer.MAX_VALUE, minIdx1 = -1, secMod1 = Integer.MAX_VALUE, minMod2 = Integer.MAX_VALUE, secMod2 = Integer.MAX_VALUE, minIdx2 = -1;
int idx = 0;
for (int dig: digits) {
if (dig % 3 == 1 && dig < minMod1) {
minMod1 = dig;
minIdx1 = idx;
}
if (dig % 3 == 2 && dig < minMod2) {
minMod2 = dig;
minIdx2 = idx;
}
++idx;
}
idx = 0;
for (int dig: digits) {
if (dig % 3 == 1 && dig < secMod1 && idx != minIdx1) {
secMod1 = dig;
}
if (dig % 3 == 2 && dig < secMod2 && idx != minIdx2) {
secMod2 = dig;
}
++idx;
}
int flag = 0;
if (sum % 3 == 1) {
if (minMod1 != Integer.MAX_VALUE) {
flag = 0;
for (i=n-1; i>=0; --i) {
if (flag == 0 && digits[i] == minMod1) {
++flag;
} else {
sb.append(digits[i]);
}
}
} else {
flag = 0;
for (i=n-1; i>=0; --i) {
if (flag < 2) {
if (digits[i] == minMod2 || digits[i] == secMod2) {
++flag;
} else {
sb.append(digits[i]);
}
} else {
sb.append(digits[i]);
}
}
}
} else {
if (minMod2 != Integer.MAX_VALUE) {
flag = 0;
for (i=n-1; i>=0; --i) {
if (flag == 0 && digits[i] == minMod2) {
++flag;
} else {
sb.append(digits[i]);
}
}
} else {
flag = 0;
for (i=n-1; i>=0; --i) {
if (flag < 2) {
if (digits[i] == minMod1 || digits[i] == secMod1) {
++flag;
} else {
sb.append(digits[i]);
}
} else {
sb.append(digits[i]);
}
}
}
}
return toZero(sb.toString());
}
}