每日一题
爬楼梯
假设你正在爬楼梯。需要 n
阶你才能到达楼顶。
每次你可以爬 1
或 2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
n 步数到顶层 | 先走一步 | 先走两步 | 共多少种 | 总结 |
---|---|---|---|---|
1 | 1 | 0 | 1 | if f(1) return 1 |
2 | 1+1 | 2 | 2 | if f(2) return 2 |
3 | 1+1+1,1+2 | 2+1 | 3 | f3=f(3-1)+f(3-2)=3 |
4 | 1+1+1+1,1+1+2,1+2+1 | 2+1+1,2+2 | 5 | f4=f(4-1)+f(4-2)=5 |
5 | 1+1+1+1+1,1+1+1+2,1+1+2+1,1+2+1+1 | 2+1+1+1,2+2+1,2+1+2,1+2+2 | 8 | f5=f(5-1)+f(5-2) = 8 |
n | f(n-1) | f(n-2) | n | fn=f(n-1)+f(n-2) |
推导: 第n步 就等于f(n-1)+f(n-2) ⇒ 假设n=5 ⇒ f(5-1)+f(5-2) ⇒f(4)+f(3) ⇒步数为4层的有5种办法+步数为3层的有3种办法 ⇒ 5+3 ⇒ 8 ⇒ 如果5步可以到达顶层有8种不同的方法
递归
- js
/**
* 递归
* @param {number} n
* @return {number}
*/
var climbStairs = function (n) {
if (n === 1) return 1;
if (n === 2) return 2;
return climbStairs(n - 1) + climbStairs(n - 2);
};
console.log(climbStairs(5));
如果数值过大,递归会消耗大量的时间,会有超时问题
递归+map
- js
/**
* 递归+map
* @param {number} n
* @return {number}
*/
var climbStairs = function (n) {
const map = new Map();
const func = (n) => {
if (n === 1) return 1;
if (n === 2) return 2;
if (map.get(n)) {
return map.get(n);
} else {
const result = func(n - 1) + func(n - 2);
map.set(n, result);
return result;
}
};
return func(n);
};
- go
func climbStairs(n int) int {
m := map[int]int{}
var sum func(n int) int
sum = func (n int) int{
if n ==1 {
return 1
}
if n ==2 {
return 2
}
if val,ok := m[n]; ok{
return val
}else{
result := sum(n-1)+sum(n-2)
m[n] = result
return result
}
}
return sum(n)
}
循环
- js
/**
* 循环
* @param {number} n
* @return {number}
*/
var climbStairs = function (n) {
if (n === 1) return 1;
if (n === 2) return 2;
let result = 0;
let n1 = 1;
let n2 = 2;
for (let i = 3; i <= n; i++) {
result = n1 + n2;
n1 = n2;
n2 = result;
}
return result;
};
console.log(climbStairs(5));
- go
func climbStairs(n int) int {
if n==1 {
return 1
}
if n==2 {
return 2
}
result := 0
n1 :=1
n2 :=2
for i :=3; i<=n;i++ {
result = n1+n2
n1 = n2
n2 = result
}
return result
}
1. 两数之和
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。v
- 示例
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
求解
- js
/**
* 暴力求解
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function (nums, target) {
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] === target) {
return [i, j];
}
}
}
};
console.log(twoSum([3, 2, 4], 6));
/**
* 使用map
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function (nums, target) {
let map = new Map();
for (let i = 0; i < nums.length; i++) {
let current = target - nums[i];
if (map.has(current)) {
return [i, map.get(current)];
} else {
map.set(nums[i], i);
}
}
};
- go
package main
import "fmt"
// 暴力求值
func twoSum(nums []int, target int) []int {
for i := 0; i < len(nums); i++ {
for j := i + 1; j < len(nums); j++ {
if nums[i]+nums[j] == target {
return []int{i, j}
}
}
}
return []int{}
}
// map求值
func twoSum2(nums []int, target int) []int {
m := map[int]int{}
for i := 0; i < len(nums); i++ {
r := target - nums[i]
if val, ok := m[r]; ok {
return []int{i, val}
} else {
m[nums[i]] = i
}
}
return []int{}
}
func main() {
fmt.Println(twoSum2([]int{2, 7, 11, 15}, 9))
}
88. 合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1
和 nums2
,另有两个整数 m
和 n
,分别表示 nums1
和 nums2
中的元素数目。
请你 合并 nums2
w 到 nums1
中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1
中。为了应对这种情况,nums1
的初始长度为 m + n
,其中前 m
个元素表示应合并的元素,后 n
个元素为 0
,应忽略。nums2
的长度为 n
。
- 示例 1
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
- js
/**
* @param {number[]} nums1
* @param {number} m
* @param {number[]} nums2
* @param {number} n
* @return {void} Do not return anything, modify nums1 in-place instead.
*/
var merge = function (nums1, m, nums2, n) {
let i = m - 1;
let j = n - 1;
let k = m + n - 1;
while (i >= 0 && j >= 0) {
if (nums1[i] > nums2[j]) {
nums1[k] = nums1[i];
i--;
} else {
nums1[k] = nums2[j];
j--;
}
k--;
}
while (j >= 0) {
nums1[k] = nums2[j];
j--;
k--;
}
return nums1;
};
- go
func merge(nums1 []int, m int, nums2 []int, n int) {
i := m-1;
j := n-1;
k := m+n-1;
for i>=0&&j>=0 {
if nums1[i] > nums2[j] {
nums1[k] = nums1[i]
i--;
}else{
nums1[k] = nums2[j]
j--
}
k--;
}
for j>=0{
nums1[k] = nums2[j]
j--
k--
}
}
283. 移动零
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
- 示例
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
- js
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var moveZeroes = function (nums) {
let i = 0;
let j = 0;
while (i < nums.length) {
j = i;
if (nums[i] === 0) {
i++;
} else {
let k = i;
while (j > 0) {
let pre = nums[j - 1];
if (pre === 0) {
nums[j - 1] = nums[k];
nums[k] = pre;
} else {
j = 0;
}
j--;
k--;
}
i++;
}
}
return nums;
};
- go
func moveZeroes(nums []int) {
i :=0;
j :=0;
for i<len(nums){
j = i;
if nums[i] ==0 {
i++
}else{
k := i;
for j>0{
pre := nums[j-1]
if pre == 0 {
nums[j-1] = nums[k]
nums[k] = pre
}else{
j=0
}
j--
k--
}
i++
}
}
}
448. 找到所有数组中消失的数字
给你一个含 n
个整数的数组 nums
,其中 nums[i]
在区间 [1, n]
内。请你找出所有在 [1, n]
范围内但没有出现在 nums
中的数字,并以数组的形式返回结果。
- 示例
输入:nums = [4,3,2,7,8,2,3,1]
输出:[5,6]
- js
/**
* @param {number[]} nums
* @return {number[]}
*/
var findDisappearedNumbers = function (nums) {
let arr = [];
for (let i = 1; i <= nums.length; i++) {
if (!nums.includes(i)) {
arr.push(i);
}
}
return arr;
};
- go
func findDisappearedNumbers(nums []int) []int {
arr :=[]int{}
m := make(map[int]bool)
for _,v := range nums {
m[v] = true
}
for i:=1;i<=len(nums);i++{
if m[i]!= true {
arr = append(arr,i)
}
}
return arr
}
21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
- js
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} list1
* @param {ListNode} list2
* @return {ListNode}
*/
var mergeTwoLists = function (list1, list2) {
if (list1 === null && list2 === null) return list1;
const d = new ListNode(0);
let p = d;
while (list1 !== null && list2 !== null) {
if (list1.val < list2.val) {
p.next = list1;
list1 = list1.next;
} else {
p.next = list2;
list2 = list2.next;
}
p = p.next;
}
p.next = list1 ? list1 : list2;
return d.next;
};
- 通过节点方式实现
function ListNode(val, next) {
this.val = val === undefined ? 0 : val;
this.next = next === undefined ? null : next;
}
// 定义测试数据链表1: 1 -> 2 -> 4
const list1 = new ListNode(1);
list1.next = new ListNode(2);
list1.next.next = new ListNode(4);
// 定义测试数据链表2: 1 -> 3 -> 4
const list2 = new ListNode(1);
list2.next = new ListNode(3);
list2.next.next = new ListNode(4);
/**
* @param {ListNode} list1
* @param {ListNode} list2
* @return {ListNode}
*/
var mergeTwoLists = function (list1, list2) {
if (list1 === nul && list2 === null) return list1;
const dummy = new ListNode(0);
let p = dummy;
while (list1 !== null && list2 !== null) {
if (list1.val < list2.val) {
p.next = list1;
list1 = list1.next;
} else {
p.next = list2;
list2 = list2.next;
}
p = p.next;
}
p.next = list1 ? list1 : list2;
return dummy.next;
};
- 通过对象的方式实现
let l1 = {
val: 1,
next: {
val: 2,
next: {
val: 4,
},
},
};
let l2 = {
val: 1,
next: {
val: 3,
next: {
val: 4,
},
},
};
// 通过对象的方式去实现
var mergeTwoLists2 = function (l1, l2) {
if (l1 === null && l2 === null) return l1;
const d = { val: 0 };
let p = d;
while (l1 && l2) {
if (l1.val < l2.val) {
p.next = l1;
l1 = l1.next;
} else {
p.next = l2;
l2 = l2.next;
}
p = p.next;
}
p.next = l1 ? l1 : l2;
return d.next;
};
console.log(mergeTwoLists2(l1, l2));
- go
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
if list1 == nil && list2 == nil {
return list1
}
d := &ListNode{Val: 0}
p := d
for list1 != nil && list2 != nil {
if list1.Val < list2.Val {
p.Next = list1
list1 = list1.Next
} else {
p.Next = list2
list2 = list2.Next
}
p = p.Next
}
if list1 != nil {
p.Next = list1
}
if list2 != nil {
p.Next = list2
}
return d.Next
}
func main() {
// Linked list 1: 1 -> 2 -> 4
list1 := &ListNode{Val: 1}
list1.Next = &ListNode{Val: 2}
list1.Next.Next = &ListNode{Val: 4}
// Linked list 2: 1 -> 3 -> 4
list2 := &ListNode{Val: 1}
list2.Next = &ListNode{Val: 3}
list2.Next.Next = &ListNode{Val: 4}
result := mergeTwoLists(list1, list2)
p := result
for p != nil {
fmt.Printf("%d ", p.Val)
p = p.Next
}
}
83. 删除排序链表中的重复元素
给定一个已排序的链表的头 head
, 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
输入:head = [1,1,2]
输出:[1,2]
- js
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var deleteDuplicates = function (head) {
if (!head) return head;
let p = head;
while (p.next) {
if (p.val === p.next.val) {
p.next = p.next.next;
} else {
p = p.next;
}
}
return head;
};
// local
// 输入:head = [1,1,2]
// 输出:[1,2]
function ListNode(val, next) {
this.val = val === undefined ? 0 : val;
this.next = next === undefined ? null : next;
}
// 定义测试数据链表1: 1 -> 1 -> 2
const head = new ListNode(1);
head.next = new ListNode(1);
head.next.next = new ListNode(2);
head.next.next.next = new ListNode(2);
head.next.next.next.next = new ListNode(2);
/**
* @param {ListNode} head
* @return {ListNode}
*/
var deleteDuplicates = function (head) {
if (!head) return head;
let p = head;
while (p.next) {
if (p.val === p.next.val) {
p.next = p.next.next;
} else {
p = p.next;
}
}
return head;
};
console.log(deleteDuplicates(head));
- go
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func deleteDuplicates(head *ListNode) *ListNode {
if head == nil {
return head
}
p := head
for p.Next!=nil{
if p.Val == p.Next.Val {
p.Next = p.Next.Next
}else {
p = p.Next
}
}
return head
}
// local
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func deleteDuplicates(head *ListNode) *ListNode {
if head == nil {
return head
}
p := head
for p.Next != nil {
if p.Val == p.Next.Val {
p.Next = p.Next.Next
} else {
p = p.Next
}
}
return head
}
func main() {
list := &ListNode{Val: 1}
list.Next = &ListNode{Val: 1}
list.Next.Next = &ListNode{Val: 2}
result := deleteDuplicates(list)
r := result
for r != nil {
fmt.Printf("%d\n", r.Val)
r = r.Next
}
}
141. 环形链表
给你一个链表的头节点 head
,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos
不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true
。 否则,返回 false
。
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
- go
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func hasCycle(head *ListNode) bool {
a := head
b := head
for b!=nil && b.Next!=nil {
a = a.Next
b = b.Next.Next
if a == b {
return true
}
}
return false
}
- js
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var hasCycle = function (head) {
let a = head,
b = head;
while (b !== null && b.next !== null) {
a = a.next;
b = b.next.next;
if (a === b) return true;
}
return false;
};
142. 环形链表 II
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
- js
function ListNode(val) {
this.val = val;
this.next = null;
}
/**
* @param {ListNode} head
* @return {ListNode}
*/
var detectCycle = function (head) {
// let p = head
s = new Set();
while (head != null) {
if (s.has(head)) {
return head;
}
s.add(head);
head = head.next;
}
return null;
};
const list = new ListNode(3);
list.next = new ListNode(2);
list.next.next = new ListNode(0);
list.next.next.next = new ListNode(-4);
list.next.next.next.next = list.next;
console.log(detectCycle(list));
- go
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
func detectCycle(head *ListNode) *ListNode {
m := make(map[*ListNode]bool)
for head != nil {
if _, ok := m[head]; ok {
return head
}
m[head] = true
head = head.Next
}
return nil
}
func main() {
list := &ListNode{Val: 3}
list.Next = &ListNode{Val: 2}
list.Next.Next = &ListNode{Val: 0}
list.Next.Next.Next = &ListNode{Val: -4}
list.Next.Next.Next.Next = list.Next
res := detectCycle(list)
fmt.Printf("res:=%v", res.Val)
}
160. 相交链表
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
。
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
— 请注意相交节点的值不为 1,因为在链表 A 和链表 B 之中值为 1 的节点 (A 中第二个节点和 B 中第三个节点) 是不同的节点。换句话说,它们在内存中指向两个不同的位置,而链表 A 和链表 B 中值为 8 的节点 (A 中第三个节点,B 中第四个节点) 在内存中指向相同的位置。
- js
/**
* 输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
function ListNode(val) {
this.val = val;
this.next = null;
}
/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
var getIntersectionNode = function (headA, headB) {
console.log(headA, headB);
let nodeSet = new Set();
while (headA != null) {
nodeSet.add(headA);
headA = headA.next;
}
console.log(nodeSet);
while (headB != null) {
if (nodeSet.has(headB)) {
return headB;
}
headB = headB.next;
}
};
l3 = new ListNode(8);
l3.next = new ListNode(4);
l3.next.next = new ListNode(5);
l1 = new ListNode(4);
l1.next = new ListNode(1);
l1.next.next = l3;
l1.next.next.next = l3.next;
l1.next.next.next.next = l3.next.next;
l2 = new ListNode(5);
l2.next = new ListNode(6);
l2.next.next = new ListNode(1);
l2.next.next.next = l3;
l2.next.next.next.next = l3.next;
l2.next.next.next.next.next = l3.next.next;
console.log(getIntersectionNode(l1, l2));
- go
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func getIntersectionNode(headA, headB *ListNode) *ListNode {
nodeSet := make(map[*ListNode]bool)
for headA != nil {
nodeSet[headA] = true
headA = headA.Next
}
for headB != nil {
if _, ok := nodeSet[headB]; ok {
return headB
}
headB = headB.Next
}
return nil
}
func main() {
l3 := &ListNode{Val: 8}
l3.Next = &ListNode{Val: 4}
l3.Next.Next = &ListNode{Val: 5}
l1 := &ListNode{Val: 4}
l1.Next = &ListNode{Val: 1}
l1.Next.Next = l3
l1.Next.Next.Next = l3.Next
l1.Next.Next.Next.Next = l3.Next.Next
l2 := &ListNode{Val: 5}
l2.Next = &ListNode{Val: 6}
l2.Next.Next = &ListNode{Val: 1}
l2.Next.Next.Next = l3
l2.Next.Next.Next.Next = l3.Next
l2.Next.Next.Next.Next.Next = l3.Next.Next
res := getIntersectionNode(l1, l2)
fmt.Println(res.Val)
}
206. 反转链表
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
- javascript
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function (head) {
let pre = null,
cur = head;
if (head === null) return head;
while (cur) {
const next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
};
- golang
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reverseList(head *ListNode) *ListNode {
if head == nil||head.Next == nil {
return head
}
var pre *ListNode = nil
cur := head
for cur !=nil {
next := cur.Next
cur.Next = pre
pre = cur
cur = next
}
return pre
}
234. 回文链表
给你一个单链表的头节点 head
,请你判断该链表是否为回文链表。如果是,返回 true
;否则,返回 false
。
输入:head = [1,2,2,1]
输出:true
- javascript
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var isPalindrome = function (head) {
let curArr = [];
while (head) {
curArr.push(head.val);
head = head.next;
}
for (let i = 0; i < curArr.length; i++) {
if (curArr[i] != curArr[curArr.length - 1 - i]) return false;
}
return true;
};
- golang
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func isPalindrome(head *ListNode) bool {
arr := []int{}
for head !=nil {
arr = append(arr,head.Val)
head = head.Next
}
for i:=0;i<len(arr);i++ {
if arr[i] != arr[len(arr)-1-i] {
return false
}
}
return true
}
876. 链表的中间结点
给你单链表的头结点 head
,请你找出并返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
输入:head = [1,2,3,4,5]
输出:[3,4,5]
解释:链表只有一个中间结点,值为 3 。
- javascript
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var middleNode = function(head) {
let slow = fast = head
while(fast&&fast.next){
slow = slow.next
fast = fast.next.next
}
return slow
};
- golang
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func middleNode(head *ListNode) *ListNode {
slow := head
fast := head
for fast!=nil && fast.Next !=nil{
slow = slow.Next
fast = fast.Next.Next
}
return slow
}
剑指 Offer 22. 链表中倒数第 k 个节点
输入一个链表,输出该链表中倒数第 k 个节点。为了符合大多数人的习惯,本题从 1 开始计数,即链表的尾节点是倒数第 1 个节点。
例如,一个链表有 6
个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6
。这个链表的倒数第 3
个节点是值为 4
的节点。
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
- javascript
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var getKthFromEnd = function(head, k) {
let arr =[]
while(head){
arr.push(head)
head = head.next
}
return arr[arr.length-k]
};
- golang
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func getKthFromEnd(head *ListNode, k int) *ListNode {
arr :=[]*ListNode{}
for head!=nil{
arr = append(arr,head)
head = head.Next
}
return arr[len(arr)-k]
}
232. 用栈实现队列
难度:简单
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
):
实现 MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
说明:
- 你 只能 使用标准的栈操作 —— 也就是只有
push to top
,peek/pop from top
,size
, 和is empty
操作是合法的。 - 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
示例 1:
输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]
解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false
- javascritpt
var MyQueue = function () {
this.InStack = [];
this.OutStack = [];
};
/**
* @param {number} x
* @return {void}
*/
MyQueue.prototype.push = function (x) {
this.InStack.push(x);
};
/**
* @return {number}
*/
MyQueue.prototype.pop = function () {
if (!this.OutStack.length) {
this.toOutStack();
}
return this.OutStack.pop();
};
/**
* @return {number}
*/
MyQueue.prototype.peek = function () {
if (!this.OutStack.length) {
this.toOutStack();
}
return this.OutStack[this.OutStack.length - 1];
};
/**
* @return {boolean}
*/
MyQueue.prototype.empty = function () {
return this.OutStack.length === 0 && this.InStack.length === 0;
};
MyQueue.prototype.toOutStack = function () {
while (this.InStack.length) {
this.OutStack.push(this.InStack.pop());
}
};
- golang
type MyQueue struct {
inStack,outStack []int
}
func Constructor() MyQueue {
return MyQueue{}
}
func (this *MyQueue) Push(x int) {
this.inStack = append(this.inStack,x)
}
func (this *MyQueue) Pop() int {
if len(this.outStack) == 0 {
this.ToOutStack()
}
x := this.outStack[len(this.outStack)-1]
this.outStack = this.outStack[:len(this.outStack)-1]
return x
}
func (this *MyQueue) Peek() int {
if len(this.outStack) == 0 {
this.ToOutStack()
}
return this.outStack[len(this.outStack)-1]
}
func (this *MyQueue) Empty() bool {
return len(this.inStack) == 0 && len(this.outStack) == 0
}
func (this *MyQueue) ToOutStack() {
for len(this.inStack) > 0 {
this.outStack = append(this.outStack,this.inStack[len(this.inStack)-1])
this.inStack = this.inStack[:len(this.inStack)-1]
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* obj := Constructor();
* obj.Push(x);
* param_2 := obj.Pop();
* param_3 := obj.Peek();
* param_4 := obj.Empty();
*/
-- local
package main
import "fmt"
type MyQueue struct {
InStack []int
OutStack []int
}
func Constructor() MyQueue {
return MyQueue{}
}
func (this *MyQueue) Push(x int) {
this.InStack = append(this.InStack, x)
}
func (this *MyQueue) Pop() int {
if len(this.OutStack) == 0 {
this.ToOutStack()
}
index := len(this.OutStack) - 1
deletedElement := this.OutStack[index]
this.OutStack = append(this.OutStack[:index], this.OutStack[index+1:]...)
return deletedElement
}
func (this *MyQueue) Peek() int {
if len(this.OutStack) == 0 {
this.ToOutStack()
}
return this.OutStack[len(this.OutStack)-1]
}
func (this *MyQueue) Empty() bool {
return len(this.InStack) == 0 && len(this.OutStack) == 0
}
func (this *MyQueue) ToOutStack() {
for len(this.InStack) > 0 {
endIndex := len(this.InStack) - 1
endVal := this.InStack[endIndex]
this.InStack = append(this.InStack[:endIndex], this.InStack[endIndex+1:]...)
this.OutStack = append(this.OutStack, endVal)
}
}
func main() {
m := Constructor()
m.Push(1)
m.Push(2)
m.Pop()
fmt.Printf("InStack=%d --- OutStack=%d\n", m.InStack, m.OutStack)
}
394. 字符串解码
难度:中等
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string]
,表示其中方括号内部的 encoded_string
正好重复 k
次。注意 k
保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k
,例如不会出现像 3a
或 2[4]
的输入。
示例 1:
输入:s = "3[a]2[bc]"
输出:"aaabcbc"
示例 2:
输入:s = "3[a2[c]]"
输出:"accaccacc"
- javascript
/**
* @param {string} s
* @return {string}
*/
var decodeString = function(s) {
let numStack = [],strStack =[],str = '',num = 0;
for (let i=0;i<s.length;i++){
const item = s[i];
if(!isNaN(item)){
num =num *10 + parseInt(item)
}else if(item ==='['){
strStack.push(str)
str = ''
numStack.push(num)
num = 0
}else if(item === ']'){
const endNum = numStack.pop()
const endStr = strStack.pop()
str = endStr + str.repeat(endNum)
}else {
str += item
}
}
return str
};
- golang
func decodeString(s string) string {
numStack := []int{}
strStack := []string{}
num := 0
str := ""
for i:=0;i<len(s);i++{
item := s[i]
if numValue,error := strconv.Atoi(string(item)); error == nil {
num = num * 10 + numValue
} else if string(item) == "[" {
strStack = append(strStack,str)
str = ""
numStack = append(numStack,num)
num = 0
} else if string(item) == "]" {
numIndex := len(numStack) - 1
strIndex := len(strStack) - 1
currentNum := numStack[numIndex]
currentStr := strStack[strIndex]
numStack = append(numStack[:numIndex],numStack[numIndex+1:]...)
strStack = append(strStack[:strIndex],strStack[strIndex+1:]...)
str = currentStr + strings.Repeat(str,currentNum)
} else {
str += string(item)
}
}
return str
}
101. 对称二叉树
难度:简单
给你一个二叉树的根节点 root
, 检查它是否轴对称。
输入:root = [1,2,2,3,4,4,3]
输出:true
- javascript
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {boolean}
*/
var isSymmetric = function (root) {
if (!root) return true;
const dfs = (left, right) => {
if (left !== null && right === null) return false;
else if (left === null && right !== null) return false;
else if (left === null && right === null) return true;
else if (left.val !== right.val) return false;
return dfs(left.left, right.right) && dfs(left.right, right.left);
};
return dfs(root.left, root.right);
};
- golang
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isSymmetric(root *TreeNode) bool {
if root == nil {
return true
}
var dfs func(left *TreeNode, right *TreeNode) bool
dfs = func(left *TreeNode, right *TreeNode) bool {
if left !=nil && right == nil {
return false
} else if left ==nil && right !=nil {
return false
} else if left == nil && right == nil {
return true
} else if left.Val != right.Val {
return false
}
return dfs(left.Left,right.Right) && dfs(left.Right,right.Left)
}
return dfs(root.Left,root.Right)
}
144. 二叉树的前序遍历
难度:简单
给你二叉树的根节点 root
,返回它节点值的 前序 **遍历。
输入:root = [1,null,2,3]
输出:[1,2,3]
- javascript
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[]}
*/
var preorderTraversal = function (root) {
let arr = [];
const dfs = (root) => {
if (!root) return [];
arr.push(root.val);
dfs(root.left);
dfs(root.right);
};
dfs(root);
return arr;
};
- golang
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func preorderTraversal(root *TreeNode) []int {
arr := []int{}
var dfs func(node *TreeNode)
dfs = func(node *TreeNode){
if node != nil {
arr = append(arr,node.Val)
dfs(node.Left)
dfs(node.Right)
}
}
dfs(root)
return arr
}
94. 二叉树的中序遍历
难度:简单
给定一个二叉树的根节点 root
,返回 它的 中序 遍历 。
输入:root = [1,null,2,3]
输出:[1,3,2]
- javascript
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[]}
*/
var inorderTraversal = function(root) {
let arr = []
const dfs = (root) =>{
if(!root) return []
dfs(root.left)
arr.push(root.val)
dfs(root.right)
}
dfs(root)
return arr
};
- golang
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func inorderTraversal(root *TreeNode) []int {
arr := []int{}
var dfs func(node *TreeNode)
dfs = func(node *TreeNode) {
if node !=nil {
dfs(node.Left)
arr = append(arr,node.Val)
dfs(node.Right)
}
}
dfs(root)
return arr
}
145. 二叉树的后序遍历
难度:简单
给你一棵二叉树的根节点 root
,返回其节点值的 后序遍历 。
输入:root = [1,null,2,3]
输出:[3,2,1]
- javascript
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[]}
*/
var postorderTraversal = function(root) {
let arr =[]
const dfs = (root) =>{
if(!root) return []
dfs(root.left)
dfs(root.right)
arr.push(root.val)
}
dfs(root)
return arr
};
- golang
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func postorderTraversal(root *TreeNode) []int {
arr := []int{}
var dfs func(node *TreeNode)
dfs = func(node *TreeNode) {
if node !=nil {
dfs(node.Left)
dfs(node.Right)
arr = append(arr,node.Val)
}
}
dfs(root)
return arr
}
110. 平衡二叉树
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
输入:root = [3,9,20,null,null,15,7]
输出:true
- typescript
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function isBalanced(root: TreeNode | null): boolean {
if (!root) return true;
const getHeight = (node: TreeNode): number => {
if (!node) return 0;
return Math.max(getHeight(node.left), getHeight(node.right)) + 1;
};
return (
Math.abs(getHeight(root.left) - getHeight(root.right)) <= 1 &&
isBalanced(root.left) &&
isBalanced(root.right)
);
}
- golang
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func getAbs (a int) int{
if a < 0 {
return -1 * a
}
return a
}
func getMax (x,y int)int {
if x > y {
return x
}
return y
}
func getHeight (node *TreeNode) int {
if node == nil {
return 0
}
return getMax(getHeight(node.Left),getHeight(node.Right)) + 1
}
func isBalanced(root *TreeNode) bool {
if root == nil {
return true
}
return getAbs(getHeight(root.Left) - getHeight(root.Right)) <=1 && isBalanced(root.Left) && isBalanced(root.Right)
}
104. 二叉树的最大深度
给定一个二叉树 root
,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
输入:root = [3,9,20,null,null,15,7]
输出:3
- typescript
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function maxDepth(root: TreeNode | null): number {
if (!root) return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
- golang
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func getMax (x,y int) int {
if x > y {
return x
}
return y
}
func maxDepth(root *TreeNode) int {
if root == nil {
return 0
}
return getMax(maxDepth(root.Left),maxDepth(root.Right)) + 1
}
226. 翻转二叉树
给你一棵二叉树的根节点 root
,翻转这棵二叉树,并返回其根节点。
输入:root = [3,1,6]
输出:[3,6,1]
- typescript
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function invertTree(root: TreeNode | null): TreeNode | null {
if (!root) return null;
const middle = root.left;
root.left = root.right;
root.right = middle;
invertTree(root.left);
invertTree(root.right);
return root;
}
- golang
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func invertTree(root *TreeNode) *TreeNode {
if root == nil {
return nil
}
m := root.Left
root.Left = root.Right
root.Right = m
invertTree(root.Left)
invertTree(root.Right)
return root
}
49. 字母异位词分组
难度:中等
思路:
1 对字符串的每一个字符进行排序
2 把排序后的字符相等的归位一类,放在一个数组中
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
- 示例 1
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"];
输出: [["bat"], ["nat", "tan"], ["ate", "eat", "tea"]];
- typescript
function groupAnagrams(strs: string[]): string[][] {
const map = new Map();
for (let str of strs) {
const key = Array.from(str).sort().toString();
const list = map.get(key) ? map.get(key) : new Array();
list.push(str);
map.set(key, list);
}
return Array.from(map.values());
}
- golang
func groupAnagrams(strs []string) [][]string {
m := map[string][]string{}
for _,str := range strs {
s := []byte(str)
sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })
sortKey := string(s)
m[sortKey] = append(m[sortKey],str)
}
arr := make([][]string,0,len(m))
for _,v := range m {
arr = append(arr,v)
}
return arr
}
128. 最长连续序列
难度:中等
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n)
的算法解决此问题。
思路
1 如果 nums 长度为 0 则返回 0 2 把 nums 放入 set 中
3 遍历当前数组 如果当前值减一不存在 说明当前值为最长序列的起点 然后在判断 加一的值是否存在 如果存在就更新当前最长连续序列的长度
4 遍及每一项 更新 longestStreak 最长连续序列 然后返回该值
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
function longestConsecutive(nums: number[]): number {
if (nums.length === 0) return 0;
const numSet = new Set(nums);
let longestStreak = 0;
for (let num of nums) {
if (!numSet.has(num - 1)) {
let currentNum = num;
let currentStreak = 1;
while (numSet.has(currentNum + 1)) {
currentNum += 1;
currentStreak += 1;
}
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;
}
func max (a, b int) int {
if a > b {
return a
}
return b
}
func longestConsecutive(nums []int) int {
if len(nums) == 0 {
return 0
}
m := make(map[int]int)
longestStreak := 0
for _,n := range nums {
m[n] = 1
}
for _,num := range nums {
if _,ok := m[num - 1]; !ok {
currentNum := num
currentStreak := 1
for m[currentNum + 1] != 0 {
currentNum++
currentStreak++
}
longestStreak = max(longestStreak, currentStreak)
}
}
return longestStreak
}
11. 盛最多水的容器
给定一个长度为 n
的整数数组 height
。有 n
条垂线,第 i
条线的两个端点是 (i, 0)
和 (i, height[i])
。
找出其中的两条线,使得它们与 x
轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
输入:height = [1,1]
输出:1
- TypeScript
function maxArea(height: number[]): number {
let l = 0,r = height.length - 1, ans = 0;
while (l < r) {
const area = Math.min(height[l],height[r]) * (r - l)
ans = Math.max(ans,area)
if(height[l] <= height[r]){
l++
}else{
r--
}
}
return ans
};
- Go
func min(a, b int)int {
if a < b {
return a
}
return b
}
func max(a, b int)int {
if a > b {
return a
}
return b
}
func maxArea(height []int) int {
l := 0;
r := len(height) - 1;
ans := 0;
for l < r {
area := min(height[l],height[r]) * (r - l)
ans = max(ans,area)
if height[l] <= height[r] {
l++
}else {
r--
}
}
return ans
}
15. 三数之和
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请
你返回所有和为 0
且不重复的三元组。
**注意:**答案中不可以包含重复的三元组。
- 示例 1
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
- 示例 2
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
- TypeScript
function threeSum(nums: number[]): number[][] {
const n = nums.length
const arr = nums.sort((a,b)=>a - b)
const result = []
for (let i=0;i<n-2;i++){
if(i>0&&arr[i] == arr[i-1]){
continue
}
let left = i+1;
let right = n-1;
while (left < right) {
const sum = arr[i]+arr[left]+arr[right];
if (sum === 0){
result.push([arr[i],arr[left],arr[right]])
left++
right--
while(left < right && arr[left] === arr[left-1]){
left++
}
while (left < right && arr[right] === arr[right+1]){
right--
}
}else if (sum < 0){
left++
}else{
right--
}
}
}
return result
};
- Go
func threeSum(nums []int) [][]int {
n := len(nums)
sort.Ints(nums)
result := [][]int{}
for i := 0; i < n-2; i++ {
if i > 0 && nums[i] == nums[i-1] {
continue
}
left, right := i+1, n-1
for left < right {
sum := nums[i] + nums[left] + nums[right]
if sum == 0 {
result = append(result, []int{nums[i], nums[left], nums[right]})
left++
right--
for left < right && nums[left] == nums[left-1] {
left++
}
for left < right && nums[right] == nums[right+1] {
right--
}
} else if sum < 0 {
left++
} else {
right--
}
}
}
return result
}
42. 接雨水
难度:困难
给定 n
个非负整数表示每个宽度为 1
的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
- 示例 1
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
- 示例 2
输入:height = [4,2,0,3,2,5]
输出:9
- TypeScript
function trap(height: number[]): number {
let l = 0, r = height.length - 1;
let lMax = height[l],rMax = height[r];
let ans = 0;
while( l < r) {
if(lMax < rMax) {
ans += lMax - height[l]
l++
lMax = Math.max(lMax,height[l])
}else {
ans += rMax - height[r]
r--
rMax = Math.max(rMax,height[r])
}
}
return ans
};
- Go
func max (a, b int)int {
if a > b {
return a
}
return b
}
func trap(height []int) int {
l,r := 0,len(height) - 1
lMax,rMax := height[l],height[r]
ans := 0
for l < r {
if lMax < rMax {
ans += lMax - height[l]
l++
lMax = max(lMax,height[l])
} else {
ans += rMax - height[r]
r--
rMax = max(rMax,height[r])
}
}
return ans
}
438. 找到字符串中所有字母异位词
难度:中等
给定两个字符串s
和p
,找到s
中所有p
的异位词的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
- 示例 1
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
- 示例 2
输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。
- TypeScript
function findAnagrams(s: string, p: string): number[] {
let sLen = s.length,pLen = p.length;
let ans = [];
if (sLen < pLen){
return []
}
let sCount = new Array(26).fill(0)
let pCount = new Array(26).fill(0)
for (let i = 0; i < pLen; ++i){
++sCount[s[i].charCodeAt(0) - "a".charCodeAt(0)]
++pCount[p[i].charCodeAt(0) - "a".charCodeAt(0)]
}
if(sCount.toString() === pCount.toString()){
ans.push(0)
}
for (let i = 0; i< sLen - pLen; ++i){
--sCount[s[i].charCodeAt(0) - "a".charCodeAt(0)]
++sCount[s[(i + pLen)].charCodeAt(0) - "a".charCodeAt(0)]
if(sCount.toString() === pCount.toString()){
ans.push(i + 1)
}
}
return ans
};
- Go
func findAnagrams(s string, p string) []int {
sLen, pLen := len(s), len(p)
ans := []int{}
if sLen < pLen {
return []int{}
}
var sCount, pCount [26]int
for i := 0; i < pLen; i++ {
sCount[s[i]-'a']++
pCount[p[i]-'a']++
}
if sCount == pCount {
ans = append(ans, 0)
}
for i := 0; i < sLen-pLen; i++ {
sCount[s[i]-'a']--
sCount[s[i+pLen]-'a']++
if sCount == pCount {
ans = append(ans, i+1)
}
}
return ans
}
260. 只出现一次的数字 III
每日一题 【Yes】
难度:中等
给你一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。 你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。
示例
输入:nums = [1,2,1,3,2,5]
输出:[3,5]
解释:[5, 3] 也是有效的答案。
- TypeScript
function singleNumber(nums: number[]): number[] {
const map = new Map();
for (let i = 0; i < nums.length; i++) {
let item = nums[i];
if (map.get(item)) {
map.delete(item);
} else {
map.set(item, true);
}
}
return Array.from(map.keys());
}
- Go
func singleNumber(nums []int) []int {
m := map[int]bool{}
for i :=0;i<len(nums);i++ {
item := nums[i]
if m[item] {
delete(m,item)
}else {
m[item] = true
}
}
res := []int{}
for k := range m {
res = append(res,k)
}
return res
}
2652. 倍数求和
每日一题 【Yes】
难度:简单
给你一个正整数 n ,请你计算在 [1,n] 范围内能被 3、5、7 整除的所有整数之和。
返回一个整数,用于表示给定范围内所有满足约束条件的数字之和。
示例
输入:n = 7
输出:21
解释:在 [1, 7] 范围内能被 3、5、7 整除的所有整数分别是 3、5、6、7 。数字之和为 21 。
- TypeScript
function sumOfMultiples(n: number): number {
let str = 0;
for (let i = 3; i <= n; i++) {
if (i % 3 === 0 || i % 5 === 0 || i % 7 === 0) {
str += i;
}
}
return str;
}
- Go
func sumOfMultiples(n int) int {
str := 0
for i := 1; i <= n; i++ {
if i % 3 == 0 || i % 5 == 0 || i % 7 == 0 {
str += i
}
}
return str
}
1726. 同积元组
每日一题 【Yes】
难度:中等
给你一个由 不同 正整数组成的数组 nums ,请你返回满足 a _ b = c _ d 的元组 (a, b, c, d) 的数量。其中 a、b、c 和 d 都是 nums 中的元素,且 a != b != c != d 。
示例:
输入:nums = [2,3,4,6]
输出:8
解释:存在 8 个满足题意的元组:
(2,6,3,4) , (2,6,4,3) , (6,2,3,4) , (6,2,4,3)
(3,4,2,6) , (4,3,2,6) , (3,4,6,2) , (4,3,6,2)
- JavaScript
function tupleSameProduct(nums) {
const map = new Map();
const len = nums.length;
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++) {
const key = nums[i] * nums[j];
map.set(key, (map.get(key) || 0) + 1);
}
}
let ans = 0;
for (const v of map.values()) {
ans += v * (v - 1) * 4;
}
return ans;
}
- Go
package main
import "fmt"
func tupleSameProduct(nums []int) int {
n := len(nums)
m := make(map[int]int)
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
m[nums[i]*nums[j]]++
}
}
ans := 0
for _, v := range m {
ans += v * (v - 1) * 4
}
return ans
}
func main() {
res := tupleSameProduct([]int{2, 3, 4, 6})
fmt.Println(res)
}
2525. 根据规则将箱子分类
给你四个整数 length ,width ,height 和 mass,分别表示一个箱子的三个维度和质量,请你返回一个表示箱子类别的字符串。
如果满足以下条件 那么箱子是"Bulky"的: 箱子至少有一个维度大于等于$10^2$。或者箱子的体积大于等于$10^9$。
如果箱子的质量大于等于 100,那么箱子是"Heavy"的。
如果箱子同时是"Bulky"和"Heavy",那么返回类别为"Both"。
如果箱子既不是"Bulky",也不是"Heavy",那么返回类别为"Neither"。
如果箱子是"Bulky"但不是"Heavy",那么返回类别为"Bulky"。
如果箱子是"Heavy"但不是"Bulky",那么返回类别为"Heavy"。
注意,箱子的体积等于箱子的长度、宽度和高度的乘积。
示例
输入:length = 1000, width = 35, height = 700, mass = 300
输出:"Heavy"
解释:
箱子没有任何维度大于等于 104 。
体积为 24500000 <= 109 。所以不能归类为 "Bulky" 。
但是质量 >= 100 ,所以箱子是 "Heavy" 的。
由于箱子不是 "Bulky" 但是是 "Heavy" ,所以我们返回 "Heavy" 。
- JavaScript
/**
* @param {number} length
* @param {number} width
* @param {number} height
* @param {number} mass
* @return {string}
*/
var categorizeBox = function (length, width, height, mass) {
const pow4 = Math.pow(10, 4);
const pow9 = Math.pow(10, 9);
const l = length,
w = width,
h = height,
m = mass;
const res = [];
if (l >= pow4 || w >= pow4 || h >= pow4 || m >= pow4 || l * w * h >= pow9) {
res.push("Bulky");
}
if (m >= 100) {
res.push("Heavy");
}
if (res.length === 2) {
return "Both";
}
if (res.length === 0) {
return "Neither";
}
if (res.length === 1) {
return res[0];
}
};
let l = 1000,
w = 1000,
h = 1000,
m = 1000;
console.log(categorizeBox(2909, 3968, 3272, 727));
2678. 老人的数目
难度:简单
给你一个下标从 0 开始的字符串 details 。details 中每个元素都是一位乘客的信息,信息用长度为 15 的字符串表示,表示方式如下:
前十个字符是乘客的手机号码。 接下来的一个字符是乘客的性别。 接下来两个字符是乘客的年龄。 最后两个字符是乘客的座位号。 请你返回乘客中年龄 严格大于 60 岁 的人数。
示例
输入:details = ["7868190130M7522","5303914400F9211","9273338290F4010"]
输出:2
解释:下标为 0 ,1 和 2 的乘客年龄分别为 75 ,92 和 40 。所以有 2 人年龄大于 60 岁。
- JavaScript
/**
* @param {string[]} details
* @return {number}
*/
var countSeniors = function(details) {
let num = 0;
details.forEach((item)=>{
const curStr = item.slice(item.length-4,item.length-4+2)
if(curStr > 60){
num++
}
})
return num
};
const details = ["7868190130M7522","5303914400F9211","9273338290F4010"]
const details1 = ["1313579440F2036","2921522980M5644"]
console.log(countSeniors(details1))