劍指offer第五週殘缺版
73. 數組中只出現一次的兩個數字
一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。
請寫程序找出這兩個只出現一次的數字。
你可以假設這兩個數字一定存在。
樣例
輸入:[1,2,3,3,4,4]
輸出:[1,2]
數組中只有兩個數字出現一次,其餘數字都出現兩次。
根據 a ^ a = 0得,如果將數組所有數字做異或即得到 此唯獨出現一次的兩個數字的異或;
然後根據位 進行分組,即可;
class Solution {
public int[] findNumsAppearOnce(int[] nums) {
int res = 0;
for(int num : nums)res ^= num;
res &= (-res);
int[] ans = new int[2];
for(int i : nums){
if((i & res) == res) ans[0] ^= i;
else ans[1] ^= i;
}
return ans;
}
}
74. 數組中唯一隻出現一次的數字
在一個數組中除了一個數字只出現一次之外,其他數字都出現了三次。
請找出那個只出現一次的數字。
你可以假設滿足條件的數字一定存在。
思考題:
- 如果要求只使用 O(n)O(n) 的時間和額外 O(1)O(1) 的空間,該怎麼做呢?
樣例
輸入:[1,1,1,2,2,2,3,4,4,4]
輸出:3
方法一:將nums數組中所有數分爲不同的位數去看,一個數出現一次,其餘全部出現三次,其它數字在它的位上出現的次數一定是3此;
比如: 3 — 11,那麼 3在 第0位和第1位一定出現3次
而 5— 101 ,那麼 最後一位出現 6次,中間出現3次,首位出現3次; 如果有個數只出現一次,則打破此平衡,不再是3的倍數
class Solution {
public int findNumberAppearingOnce(int[] nums) {
// 記錄 每一位 上 出現1 的個數
int[] count = new int[32];
for(int num : nums){
for(int i = 0; i < 32; i ++){
count[i] += num & 1;
num >>>= 1;
}
}
int res = 0, m = 3;
// 將出現次數不是3的整倍數的位上 取爲1;
for(int i = 0; i < 32; i ++){
res <<= 1;
// 如果 出現 4 或者 1 次 等,則 res的此爲 爲1;
res |= count[31 - i] % m;
}
return res;
}
}
75. 和爲S的兩個數字
輸入一個數組和一個數字s,在數組中查找兩個數,使得它們的和正好是s。
如果有多對數字的和等於s,輸出任意一對即可。
你可以認爲每組輸入中都至少含有一組滿足條件的輸出。
樣例
輸入:[1,2,3,4] , sum=7
輸出:[3,4]
利用ma存每個數值需要的數
class Solution {
public int[] findNumbersWithSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<>();
for(int num : nums){
int need = target - num;
Integer temp = map.get(need);
if(temp == null)map.put(num,need);
else return new int[] {need,temp};
}
return null;
}
}
76. 和爲S的連續正數序列
輸入一個正數s,打印出所有和爲s的連續正數序列(至少含有兩個數)。
例如輸入15,由於1+2+3+4+5=4+5+6=7+8=15,所以結果打印出3個連續序列1~5、4~6和7~8。
樣例
輸入:15
輸出:[[1,2,3,4,5],[4,5,6],[7,8]]
雙指針
class Solution {
public List<List<Integer> > findContinuousSequence(int sum) {
int i = 1, total = 0;
List<List<Integer>> res = new ArrayList<>();
List<Integer> temp = new ArrayList<>();
for(int k = 1; k < sum; k ++){
total += k;
temp.add(k);
while(total > sum){
temp.remove((Integer)i);
total -= i;
i++;
}
if(total == sum)res.add(new ArrayList<>(temp));
}
return res;
}
}
77. 翻轉單詞順序
輸入一個英文句子,翻轉句子中單詞的順序,但單詞內字符的順序不變。
爲簡單起見,標點符號和普通字母一樣處理。
例如輸入字符串"I am a student."
,則輸出"student. a am I"
。
樣例
輸入:"I am a student."
輸出:"student. a am I"
class Solution {
public String reverseWords(String s) {
String[] str = s.trim().split(" ");
StringBuilder sb = new StringBuilder();
for(int i = str.length - 1; i > 0; i--){
if(str[i].trim().length() == 0) continue;
sb.append(str[i].trim()).append(" ");
}
sb.append(str[0].trim());
return sb.toString();
}
}
78. 左旋轉字符串
字符串的左旋轉操作是把字符串前面的若干個字符轉移到字符串的尾部。
請定義一個函數實現字符串左旋轉操作的功能。
比如輸入字符串"abcdefg"
和數字2,該函數將返回左旋轉2位得到的結果"cdefgab"
。
注意:
- 數據保證n小於等於輸入字符串的長度。
樣例
輸入:"abcdefg" , n=2
輸出:"cdefgab"
直接string
class Solution {
public String leftRotateString(String str,int n) {
String temp = str.substring(0,n),res = str.substring(n);
res += temp;
return res;
}
}