排序
时间复杂度
冒泡排序
for (let i = 1; i < arr.length; i++) {
let flag = true;
for (let j = 0; j < arr.length - i; j++) {
if (arr[j] > arr[j + 1]) {
const temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = false;
}
}
if (flag) {
return arr;
}
}
return arr;
}
选择排序
for (let i = 1; i < arr.length; i++) {
let j = i;
const temp = arr[i];
while(j > 0 && temp > arr[j - 1]) {
arr[j] = arr[j - 1];
j--;
}
if (j !== i) {
arr.splice(j, 1, temp);
}
}
return arr;
}
希尔排序
function shellSort(arr) {
let gap = 1;
while(gap < arr.length) {
gap = gap * 3 + 1;
}
while(gap > 0) {
for (let i = gap; i < arr.length; i++) {
let temp = arr[i];
let j = i - gap;
while (j >= 0 && arr[j] > temp) {
arr[j + gap] = arr[j];
j -= gap;
}
arr[j + gap] = temp;
}
gap = Math.floor(gap/3);
}
return arr;
}
快速排序
function quickSort(arr) {
sort(arr, 0, arr.length - 1);
}
function sort(arr, l, r) {
if (l < r) {
let index = partion(arr, l, r);
sort(arr, l , index - 1);
sort(arr, index + 1, r);
}
}
function partion(arr, l, r) {
let temp = arr[l], i = l, j = r;
while(i < j) {
while(arr[j] > temp && i < j) {
j --;
}
while(arr[i] < temp && i < j) {
i ++;
}
swap(arr, i, j);
}
swap(arr, i, j);
return i;
}
function swap(arr, i, j) {
let k = arr[i];
arr[i] = arr[j];
arr[j] = k;
}
数组
盛水最多的容器 11题
双指针
/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function(height) {
let i = 0, j = height.length - 1;
let res = -1;
while(i < j) {
if (height[i] < height[j]) {
res = Math.max(res, height[i] * (j - i));
i++;
} else {
res = Math.max(res, height[j] * (j - i));
j --;
}
}
return res;
};
除自身以外数组的乘积 题238
给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。 示例: 输入: [1,2,3,4] 输出: [24,12,8,6]
/**
* @param {number[]} nums
* @return {number[]}
*/
var productExceptSelf = function(nums) {
let res = [];
let p = 1, q = 1;
for (let i = 0; i < nums.length; i++) {
res[i] = p;
p *= nums[i];
}
for (let i = nums.length - 1; i > 0 ; i--) {
q *= nums[i];
res[i - 1] *= q;
}
return res;
};
三数之和 题15
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]
/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function(nums) {
let res = [];
nums.sort((a, b) => a - b);
for (let i = 0; i < nums.length; i++) {
let n1 = nums[i];
if (n1 > 0) break;
if (nums[i - 1] === n1 && i > 0) continue;
let left = i + 1;
let right = nums.length - 1;
while(left < right) {
let n2 = nums[left];
let n3 = nums[right];
if (n1 + n2 + n3 === 0) {
res.push([n1, n2, n3]);
while (nums[left] === n2) left++;
while (nums[right] === n3) right --;
} else if (n1 + n2 + n3 < 0) {
left ++;
} else {
right --;
}
}
}
return res;
};
链表
反转链表[题206](leetcode-cn.com/problems/re…
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
let pre = null;
let cur = head;
let tmp = null;
while(cur !== null) {
tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
};
合并两个有序链表 题21
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var mergeTwoLists = function(l1, l2) {
if (l1 === null) return l2;
if (l2 === null) return l1;
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
};
K个一组翻转链表 25题
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。 k 是一个正整数,它的值小于或等于链表的长度。 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。 示例: 给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5 说明: 你的算法只能使用常数的额外空间。 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。 题目情况解析【一个链表按k段k段翻转】 当k段能翻转==》就翻转 当不能翻转【前面的都反转完了 剩下的不足k个】==》直接加在后面 将【这一次】翻转得到新的【头部】和【上一次的尾部】相连接 当然也得记录【k+1项】因为如果直接翻转,则会丢失第【k+1项】 毕竟你反转后 屁股变成头了 找不到第【k+1项】 由第一部分析得
var reverseKGroup = function(head, k) {
let root=null
let rear=null
while(reservable(head,k)){
var arr=reserve(head,k)
if(!root){
root=arr[0]
rear=arr[1]
}else{
rear.next=arr[0]
rear=arr[1]
}
head=arr[2]
}
rear.next=head
return root
};
//翻转操作
function reserve(head,k){
if(k==1)
return [head,head,head.next]
var arr=reserve( head.next,k-1)
arr[1].next=head
return [arr[0],head,arr[2]]
}
//判断是否能翻转
function reservable(head,k){
for(let i=k;i>0;i--){
if(head==null)
return false
head=head.next
}
return true
}
链表两数相加 445
给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。 进阶: 如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。
示例:
输入:(7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 8 -> 0 -> 7
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var addTwoNumbers = function(l1, l2) {
if (!l1 || !l2) return;
let lp1 = l1, lp2 = l2, s1 = []; s2 = [];
while (lp1) {
s1.push(lp1.val);
lp1 = lp1.next;
}
while (lp2) {
s2.push(lp2.val);
lp2 = lp2.next;
}
let stack = [];
let decimal = 0;
while (s1.length || s2.length) {
let sum = (s1.pop() || 0) + (s2.pop() || 0) + decimal;
decimal = parseInt(sum / 10);
sum = sum % 10;
stack.push(sum);
}
if (decimal) {
stack.push(1);
}
let res = {};
let cur = res;
while (stack.length) {
cur.next = new ListNode(stack.pop());
cur = cur.next;
}
return res.next;
};
字符串
最长不重复子字符串长度3
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
if (s.length === 0 || s.length === 1) return s.length;
let res = '';
let stashRes = '';
for(let i = 0; i < s.length; i++) {
if (res.indexOf(s.charAt(i)) < 0) {
res = res + s.charAt(i);
} else if (res.charAt(0) === s.charAt(i)) {
res = res.substring(1);
res = res + s.charAt(i);
} else {
if (res.length > stashRes.length) stashRes = res;
const index = res.indexOf(s.charAt(i));
res = res.substring(index + 1) + s.charAt(i);
}
}
return stashRes.length > res.length ? stashRes.length : res.length;
};
字母异位词分组49
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"] 输出: [ ["ate","eat","tea"], ["nat","tan"], ["bat"] ] 说明:
所有输入均为小写字母。 不考虑答案输出的顺序。
/**
* @param {string[]} strs
* @return {string[][]}
*/
// 字母异位词 指字母相同,但排列不同的字符串。例如eat ate tea tae...
// 利用map数据结构。给strs中的每个单词都对应一个长度为26的数组(数组中的每个值为单词中各个英文字母出现的次数),数组中,索引0,1,2,3,4......分别对应a,b,c,d,e......,需要利用英文字母的ascii值做一下转换。利用这个数组记录单词中每个字母出现的次数,然后将这个数组转化为字符串,作为Map的键名,键值为字母出现次数相同的单词。最后遍历Map,把每个键值都push进结果数组中即可。
var groupAnagrams = function(strs) {
if(!strs){
return [];
}
let map =new Map(); //
for(let str of strs){
let char = new Array(26).fill(0); //
for(let i=0;i<str.length;i++){
let ascii = str.charCodeAt(i)-97;//a对应ascii值为97 减去97即可转换为数组索引0,1...
char[ascii]++;
}
let key = char.join("");
if(map.has(key)){ //
map.set(key,[...map.get(key),str])
}else{
map.set(key,[str]);
}
}
let res = [];
for(let [key,value] of map){ //
res.push(value)
}
return res;
}