[0081]按奇偶排序數組
給定一個非負整數數組 A,返回一個數組,在該數組中, A 的所有偶數元素之後跟着所有奇數元素。
你可以返回滿足此條件的任何數組作爲答案。 示例:
輸入:[3,1,2,4]
輸出:[2,4,3,1]
輸出 [4,2,3,1],[2,4,1,3] 和 [4,2,1,3] 也會被接受。
提示:
1 <= A.length <= 5000
0 <= A[i] <= 5000
方法一:排序
class Solution {
public int[] sortArrayByParity(int[] A) {
Integer[] B = new Integer[A.length];
for (int t = 0; t < A.length; ++t)
B[t] = A[t];
Arrays.sort(B, (a, b) -> Integer.compare(a%2, b%2));
for (int t = 0; t < A.length; ++t)
A[t] = B[t];
return A;
/* Alternative:
return Arrays.stream(A)
.boxed()
.sorted((a, b) -> Integer.compare(a%2, b%2))
.mapToInt(i -> i)
.toArray();
*/
}
}
方法二:兩次掃描
class Solution {
public int[] sortArrayByParity(int[] A) {
int[] ans = new int[A.length];
int t = 0;
for (int i = 0; i < A.length; ++i)
if (A[i] % 2 == 0)
ans[t++] = A[i];
for (int i = 0; i < A.length; ++i)
if (A[i] % 2 == 1)
ans[t++] = A[i];
return ans;
}
}
方法三:原地算法
維護兩個指針 i 和 j,循環保證每刻小於 i 的變量都是偶數(也就是 A[k] % 2 == 0 當 k < i),所有大於 j 的都是奇數。
所以, 4 種情況針對 (A[i] % 2, A[j] % 2):
如果是 (0, 1),那麼 i++ 並且 j–。
如果是 (1, 0),那麼交換兩個元素,然後繼續。
如果是 (0, 0),那麼說明 i 位置是正確的,只能 i++。
如果是 (1, 1),那麼說明 j 位置是正確的,只能 j–。
通過這 4 種情況,循環不變量得以維護,並且 j-i 不斷變小。最終就可以得到奇偶有序的數組。
class Solution {
public int[] sortArrayByParity(int[] A) {
int i = 0, j = A.length - 1;
while (i < j) {
if (A[i] % 2 > A[j] % 2) {
int tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
if (A[i] % 2 == 0) i++;
if (A[j] % 2 == 1) j--;
}
return A;
}
}
[0082]重新排列數組
給你一個數組 nums ,數組中有 2n 個元素,按 [x1,x2,…,xn,y1,y2,…,yn] 的格式排列。
請你將數組按 [x1,y1,x2,y2,…,xn,yn] 格式重新排列,返回重排後的數組。
示例 1:
輸入:nums = [2,5,1,3,4,7], n = 3
輸出:[2,3,5,4,1,7]
解釋:由於 x1=2, x2=5, x3=1, y1=3, y2=4, y3=7 ,所以答案爲 [2,3,5,4,1,7]
示例 2:
輸入:nums = [1,2,3,4,4,3,2,1], n = 4
輸出:[1,4,2,3,3,2,4,1]
示例 3:
輸入:nums = [1,1,2,2], n = 2
輸出:[1,2,1,2]
提示:
1 <= n <= 500
nums.length == 2n
1 <= nums[i] <= 10^3
方法:
class Solution {
public int[] shuffle(int[] nums, int n) {
int[] ret = new int[2 * n];
for(int i = 0; i < n; i++){
ret[2 * i] = nums[i];
ret[2 * i+1] = nums[i + n];
}
return ret;
}
}
[0083]擁有最多糖果的孩子
給你一個數組 candies 和一個整數 extraCandies ,其中 candies[i] 代表第 i 個孩子擁有的糖果數目。
對每一個孩子,檢查是否存在一種方案,將額外的 extraCandies 個糖果分配給孩子們之後,此孩子有 最多 的糖果。注意,允許有多個孩子同時擁有 最多 的糖果數目。
示例 1:
輸入:candies = [2,3,5,1,3], extraCandies = 3
輸出:[true,true,true,false,true]
解釋:
孩子 1 有 2 個糖果,如果他得到所有額外的糖果(3個),那麼他總共有 5 個糖果,他將成爲擁有最多糖果的孩子。
孩子 2 有 3 個糖果,如果他得到至少 2 個額外糖果,那麼他將成爲擁有最多糖果的孩子。
孩子 3 有 5 個糖果,他已經是擁有最多糖果的孩子。
孩子 4 有 1 個糖果,即使他得到所有額外的糖果,他也只有 4 個糖果,無法成爲擁有糖果最多的孩子。
孩子 5 有 3 個糖果,如果他得到至少 2 個額外糖果,那麼他將成爲擁有最多糖果的孩子。
示例 2:
輸入:candies = [4,2,1,1,2], extraCandies = 1
輸出:[true,false,false,false,false]
解釋:只有 1 個額外糖果,所以不管額外糖果給誰,只有孩子 1 可以成爲擁有糖果最多的孩子。
示例 3:
輸入:candies = [12,1,12], extraCandies = 10
輸出:[true,false,true]
方法一:
class Solution {
public List<Boolean> kidsWithCandies(int[] candies, int extraCandies) {
List<Boolean> list = new ArrayList<Boolean>();
int maxValue = 0;
for(int i = 0; i < candies.length ; i++ )
if(candies[i] > maxValue) maxValue = candies[i];
for(int i = 0; i < candies.length ; i++ )
list.add(candies[i] +extraCandies >= maxValue ? true : false);
return list;
}
}
[0084]在既定時間做作業的學生人數
給你兩個整數數組 startTime(開始時間)和 endTime(結束時間),並指定一個整數 queryTime 作爲查詢時間。
已知,第 i 名學生在 startTime[i] 時開始寫作業並於 endTime[i] 時完成作業。
請返回在查詢時間 queryTime 時正在做作業的學生人數。形式上,返回能夠使 queryTime 處於區間 [startTime[i], endTime[i]](含)的學生人數。
示例 1:
輸入:startTime = [1,2,3], endTime = [3,2,7], queryTime = 4
輸出:1
解釋:一共有 3 名學生。
第一名學生在時間 1 開始寫作業,並於時間 3 完成作業,在時間 4 沒有處於做作業的狀態。
第二名學生在時間 2 開始寫作業,並於時間 2 完成作業,在時間 4 沒有處於做作業的狀態。
第二名學生在時間 3 開始寫作業,預計於時間 7 完成作業,這是是唯一一名在時間 4 時正在做作業的學生。
示例 2:
輸入:startTime = [4], endTime = [4], queryTime = 4
輸出:1
解釋:在查詢時間只有一名學生在做作業。
示例 3:
輸入:startTime = [4], endTime = [4], queryTime = 5
輸出:0
示例 4:
輸入:startTime = [1,1,1,1], endTime = [1,3,2,4], queryTime = 7
輸出:0
示例 5:
輸入:startTime = [9,8,7,6,5,4,3,2,1], endTime = [10,10,10,10,10,10,10,10,10], queryTime = 5
輸出:5
提示:
startTime.length == endTime.length
1 <= startTime.length <= 100
1 <= startTime[i] <= endTime[i] <= 1000
1 <= queryTime <= 1000
方法一:
class Solution {
public int busyStudent(int[] startTime, int[] endTime, int queryTime) {
int ret = 0;
for(int i = 0; i < startTime.length ; i++ )
if(startTime[i] <= queryTime && endTime[i] >= queryTime)
ret++;
return ret;
}
}
[0085]拿硬幣
桌上有 n 堆力扣幣,每堆的數量保存在數組 coins 中。我們每次可以選擇任意一堆,拿走其中的一枚或者兩枚,求拿完所有力扣幣的最少次數。
示例 1:
輸入:[4,2,1]
輸出:4
解釋:第一堆力扣幣最少需要拿 2 次,第二堆最少需要拿 1 次,第三堆最少需要拿 1 次,總共 4 次即可拿完。
示例 2:
輸入:[2,3,10]
輸出:8
限制:
1 <= n <= 4
1 <= coins[i] <= 10
方法一:
class Solution {
public int minCount(int[] coins) {
int ret = 0;
for(int i = 0; i < coins.length ; i++ ){
ret += coins[i] % 2 == 0 ? coins[i] /2 : coins[i] /2 + 1 ;
}
return ret;
}
}
[0086]旅行終點站
給你一份旅遊線路圖,該線路圖中的旅行線路用數組 paths 表示,其中 paths[i] = [cityAi, cityBi] 表示該線路將會從 cityAi 直接前往 cityBi 。請你找出這次旅行的終點站,即沒有任何可以通往其他城市的線路的城市。
題目數據保證線路圖會形成一條不存在循環的線路,因此只會有一個旅行終點站。
示例 1:
輸入:paths = [["London","New York"],["New York","Lima"],["Lima","Sao Paulo"]]
輸出:"Sao Paulo"
解釋:從 "London" 出發,最後抵達終點站 "Sao Paulo" 。本次旅行的路線是 "London" -> "New York" -> "Lima" -> "Sao Paulo" 。
示例 2:
輸入:paths = [["B","C"],["D","B"],["C","A"]]
輸出:"A"
解釋:所有可能的線路是:
"D" -> "B" -> "C" -> "A".
"B" -> "C" -> "A".
"C" -> "A".
"A".
顯然,旅行終點站是 "A" 。
示例 3:
輸入:paths = [["A","Z"]]
輸出:"Z"
方法一:
class Solution {
public String destCity(List<List<String>> paths) {
Map<String, Integer> map = new HashMap<String, Integer>();
for (List<String> list : paths)
map.put(list.get(0), 1);
for (List<String> list : paths)
if (map.get(list.get(1)) == null)
return list.get(1);
return null;
}
}
[0087]通過翻轉子數組使兩個數組相等
給你兩個長度相同的整數數組 target 和 arr 。
每一步中,你可以選擇 arr 的任意 非空子數組 並將它翻轉。你可以執行此過程任意次。
如果你能讓 arr 變得與 target 相同,返回 True;否則,返回 False 。
示例 1:
輸入:target = [1,2,3,4], arr = [2,4,1,3]
輸出:true
解釋:你可以按照如下步驟使 arr 變成 target:
1- 翻轉子數組 [2,4,1] ,arr 變成 [1,4,2,3]
2- 翻轉子數組 [4,2] ,arr 變成 [1,2,4,3]
3- 翻轉子數組 [4,3] ,arr 變成 [1,2,3,4]
上述方法並不是唯一的,還存在多種將 arr 變成 target 的方法。
示例 2:
輸入:target = [7], arr = [7]
輸出:true
解釋:arr 不需要做任何翻轉已經與 target 相等。
示例 3:
輸入:target = [1,12], arr = [12,1]
輸出:true
示例 4:
輸入:target = [3,7,9], arr = [3,7,11]
輸出:false
解釋:arr 沒有數字 9 ,所以無論如何也無法變成 target 。
示例 5:
輸入:target = [1,1,1,1,1], arr = [1,1,1,1,1]
輸出:true
提示:
target.length == arr.length
1 <= target.length <= 1000
1 <= target[i] <= 1000
1 <= arr[i] <= 1000
方法一:(實際上是比較兩個數組是否相等,參考冒泡排序)
class Solution {
public boolean canBeEqual(int[] target, int[] arr) {
if (target.length != arr.length) {
return false;
}
int[] tmp1 = new int[1001];
int[] tmp2 = new int[1001];
int len = target.length;
for(int i = 0; i < len ; i++)
{ tmp1[target[i]]++;
tmp2[arr[i]]++;
}
for(int i = 0; i < 1001 ; i++)
{
if(tmp1[i] != tmp2[i]) return false;
}
return true;
}
}
[0088]最大數值
編寫一個方法,找出兩個數字a
和b
中最大的那一個。不得使用if-else或其他比較運算符。
示例:
輸入: a = 1, b = 2
輸出: 2
方法一:
class Solution {
//公式:max(a,b) = (a + b + |a - b|) / 2
int maximum(int a, int b) {
long sum = (long)a + (long)b;
long diff = (long)a - (long)b;
long abs_diff = (diff ^ (diff >> 63)) - (diff >> 63);
return (int)((sum + abs_diff) / 2);
}
}
絕對值的位運算,爲了迴避abs,利用位運算實現絕對值功能。
以int8_t爲例:分析運算:(var ^ (var >> 7)) - (var >> 7)
var >= 0: var >> 7 => 0x00,即:(var ^ 0x00) - 0x00,異或結果爲var
var < 0: var >> 7 => 0xFF,即:(var ^ 0xFF) - 0xFF,var ^ 0xFF是在對var的全部位取反,-0xFF <=> +1, 對signed int取反加一就是取其相反數。
舉個栗子🌰:var = -3 <=> 0xFD,(var ^ 0xFF) - 0xFF= 0x02 - 0xff= 0x03
基於上述分析:
類型 絕對值位運算
int8_t (var ^ (var >> 7)) - (var >> 7)
int16_t (var ^ (var >> 15)) - (var >> 15)
int32_t (var ^ (var >> 31)) - (var >> 31)
int64_t (var ^ (var >> 63)) - (var >> 63)
代碼中(diff^ (diff >> 63)) - (diff>> 63)
就是在求取long (int64_t)
的絕對值。
方法二:
class Solution {
public int maximum(int a, int b) {
// 先考慮沒有溢出時的情況,計算 b - a 的最高位,依照題目所給提示 k = 1 時 a > b,即 b - a 爲負
int k = (b - a) >>> 31;
// 再考慮 a b 異號的情況,此時無腦選是正號的數字
int aSign = a >>> 31, bSign = b >>> 31;
// diff = 0 時同號,diff = 1 時異號
int diff = aSign ^ bSign;
// 在異號,即 diff = 1 時,使之前算出的 k 無效,只考慮兩個數字的正負關係
k = k & (diff ^ 1) | bSign & diff;
return a * k + b * (k ^ 1);
}
}
[0089]數組拆分 I
給定長度爲 2n 的數組, 你的任務是將這些數分成 n 對, 例如 (a1, b1), (a2, b2), …, (an, bn) ,使得從1 到 n 的 min(ai, bi) 總和最大。
示例 1:
輸入: [1,4,3,2]
輸出: 4
解釋: n 等於 2, 最大總和爲 4 = min(1, 2) + min(3, 4).
提示:
n 是正整數,範圍在 [1, 10000].
數組中的元素範圍在 [-10000, 10000].
方法一:排序
class Solution {
public int arrayPairSum(int[] nums) {
Arrays.sort(nums);
int sum = 0;
for (int i = 0; i < nums.length; i += 2) {
sum += nums[i];
}
return sum;
}
}
方法二:使用額外的空間
public class Solution {
public int arrayPairSum(int[] nums) {
int[] arr = new int[20001];
int lim = 10000;
for (int num: nums)
arr[num + lim]++;
int d = 0, sum = 0;
for (int i = -10000; i <= 10000; i++) {
//d:如果當前集合中有剩餘元素將被再次考慮,則此標誌設置爲 1。在從下一組中選擇元素時,會考慮已考慮的相同額外元素。
sum += (arr[i + lim] + 1 - d) / 2 * i;
d = (2 + arr[i + lim] - d) % 2;
}
return sum;
}
}
https://leetcode-cn.com/problems/array-partition-i/solution/shu-zu-chai-fen-i-by-leetcode/
[0090]獨一無二的出現次數
給你一個整數數組 arr,請你幫忙統計數組中每個數的出現次數。
如果每個數的出現次數都是獨一無二的,就返回 true;否則返回 false。
示例 1:
輸入:arr = [1,2,2,1,1,3]
輸出:true
解釋:在該數組中,1 出現了 3 次,2 出現了 2 次,3 只出現了 1 次。沒有兩個數的出現次數相同。
示例 2:
輸入:arr = [1,2]
輸出:false
示例 3:
輸入:arr = [-3,0,1,-3,1,1,1,-3,10,0]
輸出:true
提示:
1 <= arr.length <= 1000
-1000 <= arr[i] <= 1000
方法一:
class Solution {
public boolean uniqueOccurrences(int[] arr) {
HashSet<Integer> set = new HashSet<>();
int[] ret = new int[2001];
int base = 1000;
for (int i = 0; i < arr.length; i ++)
ret[arr[i] + base]++;
for (int i = 0; i < ret.length; i ++)
{
if(ret[i]!=0){
if(set.contains(ret[i])) return false;
set.add(ret[i]);
}
}
return true;
}
}
[0091]遞增順序查找樹
給你一個樹,請你 按中序遍歷 重新排列樹,使樹中最左邊的結點現在是樹的根,並且每個結點沒有左子結點,只有一個右子結點。
示例 :
輸入:[5,3,6,2,4,null,8,1,null,null,null,7,9]
5
/ \
3 6
/ \ \
2 4 8
/ / \
1 7 9
輸出:[1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9]
1
\
2
\
3
\
4
\
5
\
6
\
7
\
8
\
9
提示:
給定樹中的結點數介於 1 和 100 之間。
每個結點都有一個從 0 到 1000 範圍內的唯一整數值。
方法一:中序遍歷 + 構造新的樹
我們在樹上進行中序遍歷,就可以從小到大得到樹上的節點。我們把這些節點的對應的值存放在數組中,它們已經有序。接着我們直接根據數組構件題目要求的樹即可。
class Solution {
public TreeNode increasingBST(TreeNode root) {
List<Integer> vals = new ArrayList();
inorder(root, vals);
TreeNode ans = new TreeNode(0), cur = ans;
for (int v: vals) {
cur.right = new TreeNode(v);
cur = cur.right;
}
return ans.right;
}
public void inorder(TreeNode node, List<Integer> vals) {
if (node == null) return;
inorder(node.left, vals);
vals.add(node.val);
inorder(node.right, vals);
}
}
複雜度分析
時間複雜度:O(N)O(N),其中 NN 是樹上的節點個數。
空間複雜度:O(N)O(N)。
方法二:中序遍歷 + 更改樹的連接方式
和方法一類似,我們在樹上進行中序遍歷,但會將樹中的節點之間重新連接而不使用額外的空間。具體地,當我們遍歷到一個節點時,把它的左孩子設爲空,並將其本身作爲上一個遍歷到的節點的右孩子。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
TreeNode cur;
public TreeNode increasingBST(TreeNode root) {
TreeNode ans = new TreeNode(0);
cur = ans;
inorder(root);
return ans.right;
}
public void inorder(TreeNode node) {
if (node == null) return;
inorder(node.left);
node.left = null;
cur.right = node;
cur = node;
inorder(node.right);
}
}
複雜度分析
時間複雜度:O(N)O(N),其中 NN 是樹上的節點個數。
空間複雜度:O(H)O(H),其中 HH 是數的高度。
[0092]找出給定方程的正整數解
給出一個函數 f(x, y) 和一個目標結果 z,請你計算方程 f(x,y) == z 所有可能的正整數 數對 x 和 y。
給定函數是嚴格單調的,也就是說:
f(x, y) < f(x + 1, y)
f(x, y) < f(x, y + 1)
函數接口定義如下:
interface CustomFunction {
public:
// Returns positive integer f(x, y) for any given positive integer x and y.
int f(int x, int y);
};
如果你想自定義測試,你可以輸入整數 function_id 和一個目標結果 z 作爲輸入,其中 function_id 表示一個隱藏函數列表中的一個函數編號,題目只會告訴你列表中的 2 個函數。
你可以將滿足條件的 結果數對 按任意順序返回。
示例 1:
輸入:function_id = 1, z = 5
輸出:[[1,4],[2,3],[3,2],[4,1]]
解釋:function_id = 1 表示 f(x, y) = x + y
示例 2:
輸入:function_id = 2, z = 5
輸出:[[1,5],[5,1]]
解釋:function_id = 2 表示 f(x, y) = x * y
提示:
1 <= function_id <= 9
1 <= z <= 100
題目保證 f(x, y) == z 的解處於 1 <= x, y <= 1000 的範圍內。
在 1 <= x, y <= 1000 的前提下,題目保證 f(x, y) 是一個 32 位有符號整數。
方法一:暴力法
class Solution {
public List<List<Integer>> findSolution(CustomFunction customfunction, int z) {
List<List<Integer>> res = new ArrayList<>();
for (int i = 1; i <= 1000; i++) {
if (customfunction.f(i,1) > z) {
break;
}
for (int j = 1; j <= 1000; j++) {
if (customfunction.f(i,j) == z) {
List<Integer> list = new ArrayList<>();
list.add(i);
list.add(j);
res.add(list);
break;
} else if(customfunction.f(i,j) > z){
break;
}
}
}
return res;
}
}
時間複雜度:O(n^2)
方法二:二分查找
class Solution {
public List<List<Integer>> findSolution(CustomFunction customfunction, int z) {
List<List<Integer>> res = new ArrayList<>();
for (int i = 1; i <= 1000; i++) {
if (customfunction.f(i,1) > z) {
break;
}
int left = 1;
int right = 1000;
while (left <= right) {
int mid = (right + left) / 2;
int temp = customfunction.f(i,mid);
if (temp == z) {
List<Integer> list = new ArrayList<>();
list.add(i);
list.add(mid);
res.add(list);
break;
} else if (temp > z) {
right = mid - 1;
} else {
left = mid + 1;
}
}
}
return res;
}
}
時間複雜度:O(nlogn)
方法三:雙指針法 (給定函數是嚴格單調的)
class Solution {
public List<List<Integer>> findSolution(CustomFunction customfunction, int z) {
List<List<Integer>> res = new ArrayList<>();
int left = 1;
int right = 1000;
while (left <= 1000 && right >= 1) {
int temp = customfunction.f(left,right);
if (temp == z) {
List<Integer> list = new ArrayList<>();
list.add(left);
list.add(right);
res.add(list);
left++;
} else if (temp > z) {
right--;
} else {
left++;
}
}
return res;
}
}
時間複雜度:O(n)
[0093]只出現一次的數字
給定一個非空整數數組,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。
說明:
你的算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?
示例 1:
輸入: [2,2,1]
輸出: 1
示例 2:
輸入: [4,1,2,1,2]
輸出: 4
方法一:
異或運算有以下三個性質。
- 任何數和 0 做異或運算,結果仍然是原來的數。
- 任何數和其自身做異或運算,結果是 0。
- 異或運算滿足交換律和結合律。
class Solution {
public int singleNumber(int[] nums) {
int single = 0;
for (int num : nums) {
single ^= num;
}
return single;
}
}
- 時間複雜度:O(n),其中 n 是數組長度。只需要對數組遍歷一次。
- 空間複雜度:O(1)。
[0094]特殊等價字符串組
你將得到一個字符串數組 A。
如果經過任意次數的移動,S == T,那麼兩個字符串 S 和 T 是特殊等價的。
一次移動包括選擇兩個索引 i 和 j,且 i % 2 == j % 2,交換 S[j] 和 S [i]。
現在規定,A 中的特殊等價字符串組是 A 的非空子集 S,這樣不在 S 中的任何字符串與 S 中的任何字符串都不是特殊等價的。
返回 A 中特殊等價字符串組的數量。
示例 1:
輸入:["a","b","c","a","c","c"]
輸出:3
解釋:3 組 ["a","a"],["b"],["c","c","c"]
示例 2:
輸入:["aa","bb","ab","ba"]
輸出:4
解釋:4 組 ["aa"],["bb"],["ab"],["ba"]
示例 3:
輸入:["abc","acb","bac","bca","cab","cba"]
輸出:3
解釋:3 組 ["abc","cba"],["acb","bca"],["bac","cab"]
示例 4:
輸入:["abcd","cdab","adcb","cbad"]
輸出:1
解釋:1 組 ["abcd","cdab","adcb","cbad"]
提示:
1 <= A.length <= 1000
1 <= A[i].length <= 20
所有 A[i] 都具有相同的長度。
所有 A[i] 都只由小寫字母組成。
https://leetcode-cn.com/problems/groups-of-special-equivalent-strings/solution/te-shu-deng-jie-zi-fu-chuan-zu-by-leetcode/
方法一:
class Solution {
public int numSpecialEquivGroups(String[] A) {
Set<String> seen = new HashSet();
for (String S: A) {
int[] count = new int[52];
for (int i = 0; i < S.length(); ++i)
count[S.charAt(i) - 'a' + 26 * (i % 2)]++;
seen.add(Arrays.toString(count));
}
return seen.size();
}
}
[0095]數字的補數
給定一個正整數,輸出它的補數。補數是對該數的二進制表示取反。
示例 1:
輸入: 5
輸出: 2
解釋: 5 的二進制表示爲 101(沒有前導零位),其補數爲 010。所以你需要輸出 2 。
示例 2:
輸入: 1
輸出: 0
解釋: 1 的二進制表示爲 1(沒有前導零位),其補數爲 0。所以你需要輸出 0 。
注意:
給定的整數保證在 32 位帶符號整數的範圍內。
你可以假定二進制數不包含前導零位。
本題與 1009 https://leetcode-cn.com/problems/complement-of-base-10-integer/ 相同
方法一:
class Solution {
public int findComplement(int num) {
int temp = num, c = 0;
while(temp > 0){
temp >>= 1;
c = (c << 1) + 1;
}
return num ^ c;
}
}
[0096]最小差值 I
給你一個整數數組 A,對於每個整數 A[i],我們可以選擇處於區間 [-K, K] 中的任意數 x ,將 x 與 A[i] 相加,結果存入 A[i] 。
在此過程之後,我們得到一些數組 B。
返回 B 的最大值和 B 的最小值之間可能存在的最小差值。
示例 1:
輸入:A = [1], K = 0
輸出:0
解釋:B = [1]
示例 2:
輸入:A = [0,10], K = 2
輸出:6
解釋:B = [2,8]
示例 3:
輸入:A = [1,3,6], K = 3
輸出:0
解釋:B = [3,3,3] 或 B = [4,4,4]
提示:
1 <= A.length <= 10000
0 <= A[i] <= 10000
0 <= K <= 10000
方法一:
class Solution {
public int smallestRangeI(int[] A, int K) {
int min = A[0], max = A[0];
for (int x: A) {
min = Math.min(min, x);
max = Math.max(max, x);
}
return Math.max(0, max - min - 2*K);
}
}