1.移除元素
題目:
給你一個數組 nums 和一個值 val,你需要 原地 移除所有數值等於 val 的元素,並返回移除後數組的新長度。
不要使用額外的數組空間,你必須僅使用 O(1) 額外空間並 原地 修改輸入數組。
元素的順序可以改變。你不需要考慮數組中超出新長度後面的元素。
和昨天的重複排序類似。
思路:單次遍歷,並聲明一個變量記錄當前有效的長度,比較時,如果相等則直接進入下一輪循環,如果不相等,先把當前元素賦值給當前變量下標,然後變量自增1,(順序不能弄錯)
var removeElement = function(nums, val) {
let l = nums.length,
res = 0;
for (let i = 0; i < l; i++) {
if (nums[i] !== val) {
nums[res] = nums[i];
res++;
}
}
return res;
};
沒啥優化空間,單次遍歷,也沒遞歸,時間複雜度和空間複雜度都是最低了。
2.實現strStr()
題目:
實現 strStr() 函數。
給定一個 haystack 字符串和一個 needle 字符串,在 haystack 字符串中找出 needle 字符串出現的第一個位置 (從0開始)。如果不存在,則返回 -1。
思路:其實就是字符串的indexOf方法,不過咱肯定用原生寫。
和冒泡排序十分類似,。
思路:雙重循環,依次比較
var strStr = function(haystack, needle) {
let l = needle.length;
if (!l) return l;
let l2 = haystack.length;
if (l > l2) return -1;
for (let i = 0; i < l2; i++) {
for (let j = 0; j < l; j++) {
if (haystack[i + j] !== needle[j]) break;
if (j === l - 1) {
return i;
}
}
}
return -1;
};
問題:每個都遍歷,耗時太長
優化方向:提早跳出不必要的循環。可以在外層循環比較haystack剩餘字符串長度和needle的長度,如果前者更小,則直接跳出循環返回-1即可。
var strStr = function(haystack, needle) {
let l = needle.length;
if (!l) return l;
let l2 = haystack.length;
if (!l2) return -1;
if (l > l2) return -1;
for (let i = 0; i < l2; i++) {
if (l2 - i < l) return -1;
for (let j = 0; j < l; j++) {
if (haystack[i + j] !== needle[j]) break;
if (j === l - 1) {
return i;
}
}
}
return -1
};
3.搜索插入位置
題目:
給定一個排序數組和一個目標值,在數組中找到目標值,並返回其索引。如果目標值不存在於數組中,返回它將會被按順序插入的位置。
你可以假設數組中無重複元素。
思路:分兩種情況,一是有相等的元素,二是沒有相等的元素。
相等的情況很容易區分,不相等的時候,可以這樣,因爲原數組是排序號的,我們一直記錄比目標值小的成員的下標即可,最後返回+1的值
let l = nums.length,
j = -1;
for (let i = 0; i < l; i++) {
if (nums[i] === target) return i;
if (nums[i] < target) j = i;
}
return j+1;
優化方向:提前終止循環
let l = nums.length,
j = -1;
if (target <= nums[0]) return 0;
if (target > nums[l - 1]) return l;
for (let i = 0; i < l; i++) {
if (nums[i] === target) return i;
if (nums[i] < target) j = i;
}
return j + 1;
優化方向:二分法查找,而非單次遍歷,減少比較次數:
let left = 0;
let right = nums.length - 1;
if (target > nums[right]){ return right + 1; }
if(target<=nums[0])return 0
while (left < right) {
let index = (left + right) >>> 1;//取左中位數
if (nums[index] < target){
left = index + 1;
}else{
right = index;
}
}
return left;
4.外觀數列
題目:
「外觀數列」是一個整數序列,從數字 1 開始,序列中的每一項都是對前一項的描述。前五項如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
1 被讀作 "one 1" ("一個一") , 即 11。
11 被讀作 "two 1s" ("兩個一"), 即 21。
21 被讀作 "one 2", "one 1" ("一個二" , "一個一") , 即 1211。
給定一個正整數 n(1 ≤ n ≤ 30),輸出外觀數列的第 n 項。
注意:整數序列中的每一項將表示爲一個字符串。
思路:從左到右,雙重循環,第一次循環是記錄n的值,第二輪循環是遍歷上一輪循環的結果,根據上一輪的結果得到這一輪的結果。所以首先需要一個變量保存上一輪的結果,一個變量計算這一輪的結果。
此外,還要有一個變量記錄當前遇到的數是什麼數,一個變量記錄當前數出現的次數
遍歷上一輪的結果,比較每一個字符串和當前字符串,如果相同,則變量+1,如果不同,則先對結果拼接,然後更新當前的數,
var countAndSay = function (n) {
if (n == 1) return "1";
let res = "1",
v = "0",
a = 0,
r = "";
for (let i = 1; i < n; i++) {
let l = res.length;
for (let j = 0; j < l; j++) {
if (res[j] !== v) {
if (a) {
r += `${a}${v}`;
}
v = res[j];
a = 1;
} else {
a++;
}
}
if (a) {
r += `${a}${v}`;
}
v = "0";
res = r;
a = 0;
r = "";
}
return res;
};