目录
147. 对链表进行插入排序 Insertion Sort List 🌟🌟
148. 排序链表 Sort List 🌟🌟
149. 直线上最多的点数 Max Points On A Line 🌟🌟🌟
150. 逆波兰表达式求值 Evaluate Reverse Polish Notation 🌟🌟
🌟 每日一练刷题专栏 🌟
Golang每日一练 专栏
Python每日一练 专栏
C/C++每日一练 专栏
Java每日一练 专栏
147. 对链表进行插入排序 Insertion Sort List
给定单个链表的头 head
,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。
插入排序 算法的步骤:
- 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
- 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
- 重复直到所有输入数据插入完为止。
下面是插入排序算法的一个图形示例。部分排序的列表(黑色)最初只包含列表中的第一个元素。每次迭代时,从输入数据中删除一个元素(红色),并就地插入已排序的列表中。
对链表进行插入排序。
示例 1:
输入: head = [4,2,1,3] 输出: [1,2,3,4]
示例 2:
输入: head = [-1,5,3,4,0] 输出: [-1,0,3,4,5]
提示:
- 列表中的节点数在
[1, 5000]
范围内 -5000 <= Node.val <= 5000
代码: 插入排序
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
func build(list []int) *ListNode {
head := &ListNode{Val: -1 << 31} //-5000 <= Node.val <= 5000
for i := len(list) - 1; i >= 0; i-- {
p := &ListNode{Val: list[i]}
p.Next = head.Next
head.Next = p
}
return head
}
func (head *ListNode) travel() {
for p := head.Next; p != nil; p = p.Next {
fmt.Print(p.Val)
if p.Next != nil {
fmt.Print("->")
}
}
fmt.Println("<nil>")
}
func insertionSortList(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
dummy := &ListNode{}
dummy.Next = head
cur := head.Next
lastSorted := head
for cur != nil {
if cur.Val >= lastSorted.Val {
lastSorted = lastSorted.Next
} else {
prev := dummy
for prev.Next.Val < cur.Val {
prev = prev.Next
}
lastSorted.Next = cur.Next
cur.Next = prev.Next
prev.Next = cur
}
cur = lastSorted.Next
}
return dummy.Next
}
func main() {
nums := []int{4, 2, 1, 3}
head := build(nums)
head.travel()
head = insertionSortList(head)
head.travel()
nums2 := []int{-1, 5, 3, 4, 0}
head2 := build(nums2)
head2.travel()
head2 = insertionSortList(head2)
head2.travel()
}
输出:
4->2->1->3<nil>
1->2->3->4<nil>
-1->5->3->4->0<nil>
-1->0->3->4->5<nil>
148. 排序链表 Sort List
给你链表的头结点 head
,请将其按 升序 排列并返回 排序后的链表 。
示例 1:
输入:head = [4,2,1,3] 输出:[1,2,3,4]
示例 2:
输入:head = [-1,5,3,4,0] 输出:[-1,0,3,4,5]
示例 3:
输入:head = [] 输出:[]
提示:
- 链表中节点的数目在范围
[0, 5 * 10^4]
内 -10^5 <= Node.val <= 10^5
进阶:你可以在 O(nlogn)
时间复杂度和常数级空间复杂度下,对链表进行排序吗?
代码: 归并排序,与147题对比多了对时间和空间复杂度的要求
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
func build(list []int) *ListNode {
head := &ListNode{Val: -1 << 31} //-5000 <= Node.val <= 5000
for i := len(list) - 1; i >= 0; i-- {
p := &ListNode{Val: list[i]}
p.Next = head.Next
head.Next = p
}
return head
}
func (head *ListNode) travel() {
for p := head.Next; p != nil; p = p.Next {
fmt.Print(p.Val)
if p.Next != nil {
fmt.Print("->")
}
}
fmt.Println("<nil>")
}
func sortList(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
slow, fast := head, head.Next
for fast != nil && fast.Next != nil {
slow = slow.Next
fast = fast.Next.Next
}
mid := slow.Next
slow.Next = nil
left := sortList(head)
right := sortList(mid)
return merge(left, right)
}
func merge(a, b *ListNode) *ListNode {
dummy := &ListNode{}
cur := dummy
for a != nil && b != nil {
if a.Val < b.Val {
cur.Next = a
a = a.Next
} else {
cur.Next = b
b = b.Next
}
cur = cur.Next
}
if a != nil {
cur.Next = a
} else {
cur.Next = b
}
return dummy.Next
}
func main() {
nums := []int{4, 2, 1, 3}
head := build(nums)
head.travel()
head = sortList(head)
head.travel()
nums2 := []int{-1, 5, 3, 4, 0}
head2 := build(nums2)
head2.travel()
head2 = sortList(head2)
head2.travel()
}
输出:
4->2->1->3<nil>
1->2->3->4<nil>
-1->5->3->4->0<nil>
-1->0->3->4->5<nil>
149. 直线上最多的点数 Max Points On A Line
给你一个数组 points
,其中 points[i] = [xi, yi]
表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。
示例 1:
输入:points = [[1,1],[2,2],[3,3]] 输出:3
示例 2:
输入:points = [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]] 输出:4
提示:
1 <= points.length <= 300
points[i].length == 2
-10^4 <= xi, yi <= 10^4
points
中的所有点 互不相同
代码1: 暴力枚举
package main
import (
"fmt"
)
func maxPoints(points [][]int) int {
if len(points) < 3 {
return len(points)
}
ans := 0
for i := 0; i < len(points); i++ {
kMap := make(map[Fraction]int)
same := 1
for j := i + 1; j < len(points); j++ {
dx, dy := points[i][0]-points[j][0], points[i][1]-points[j][1]
if dx == 0 && dy == 0 {
same++
continue
}
gcd := GCD(dx, dy)
f := Fraction{
Numerator: dy / gcd,
Denominator: dx / gcd,
}
kMap[f]++
}
maxCnt := 0
for _, cnt := range kMap {
if cnt > maxCnt {
maxCnt = cnt
}
}
ans = max(ans, maxCnt+same)
}
return ans
}
type Fraction struct {
Numerator int
Denominator int
}
func GCD(a, b int) int {
if b == 0 {
return a
}
return GCD(b, a%b)
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func main() {
points := [][]int{{1, 1}, {2, 2}, {3, 3}}
fmt.Println(maxPoints(points))
points = [][]int{{1, 1}, {3, 2}, {5, 3}, {4, 1}, {2, 3}, {1, 4}}
fmt.Println(maxPoints(points))
}
代码2: 哈希表
package main
import (
"fmt"
)
func maxPoints(points [][]int) int {
if len(points) < 2 {
return len(points)
}
ans := 1
for i, p := range points {
if ans >= len(points)-i {
break
}
cnt := map[fraction]int{}
for _, q := range points[i+1:] {
k := newFraction(p, q)
cnt[*k]++
}
for _, c := range cnt {
ans = max(ans, c+1)
}
}
return ans
}
type fraction struct {
dx, dy int
}
func newFraction(p, q []int) *fraction {
dx, dy := p[1]-q[1], p[0]-q[0]
if dx == 0 {
dy = 1
} else if dy == 0 {
dx = 1
} else if dy < 0 {
dx, dy = -dx, -dy
}
g := gcd(abs(dx), abs(dy))
return &fraction{dx / g, dy / g}
}
func gcd(a, b int) int {
for b != 0 {
a, b = b, a%b
}
return a
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func main() {
points := [][]int{{1, 1}, {2, 2}, {3, 3}}
fmt.Println(maxPoints(points))
points = [][]int{{1, 1}, {3, 2}, {5, 3}, {4, 1}, {2, 3}, {1, 4}}
fmt.Println(maxPoints(points))
}
输出:
3
4
150. 逆波兰表达式求值 Evaluate Reverse Polish Notation
根据 逆波兰表示法,求表达式的值。
有效的算符包括 +
、-
、*
、/
。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
注意 两个整数之间的除法只保留整数部分。
可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:
输入:tokens = ["2","1","+","3","*"] 输出:9 解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:
输入:tokens = ["4","13","5","/","+"] 输出:6 解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:
输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"] 输出:22 解释:该算式转化为常见的中缀算术表达式为: ((10 * (6 / ((9 + 3) * -11))) + 17) + 5 = ((10 * (6 / (12 * -11))) + 17) + 5 = ((10 * (6 / -132)) + 17) + 5 = ((10 * 0) + 17) + 5 = (0 + 17) + 5 = 17 + 5 = 22
提示:
1 <= tokens.length <= 10^4
tokens[i]
是一个算符("+"
、"-"
、"*"
或"/"
),或是在范围[-200, 200]
内的一个整数
逆波兰表达式:
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
- 平常使用的算式则是一种中缀表达式,如
( 1 + 2 ) * ( 3 + 4 )
。 - 该算式的逆波兰表达式写法为
( ( 1 2 + ) ( 3 4 + ) * )
。
逆波兰表达式主要有以下两个优点:
- 去掉括号后表达式无歧义,上式即便写成
1 2 + 3 4 + *
也可以依据次序计算出正确结果。 - 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
代码1: 栈 stack
package main
import (
"fmt"
"strconv"
)
func evalRPN(tokens []string) int {
stack := make([]int, 0)
for _, t := range tokens {
if t == "+" {
a, b := stack[len(stack)-2], stack[len(stack)-1]
stack = stack[:len(stack)-2]
stack = append(stack, a+b)
} else if t == "-" {
a, b := stack[len(stack)-2], stack[len(stack)-1]
stack = stack[:len(stack)-2]
stack = append(stack, a-b)
} else if t == "*" {
a, b := stack[len(stack)-2], stack[len(stack)-1]
stack = stack[:len(stack)-2]
stack = append(stack, a*b)
} else if t == "/" {
a, b := stack[len(stack)-2], stack[len(stack)-1]
stack = stack[:len(stack)-2]
stack = append(stack, a/b)
} else {
num, _ := strconv.Atoi(t)
stack = append(stack, num)
}
}
return stack[0]
}
func main() {
tokens := []string{"2", "1", "+", "3", "*"}
fmt.Println(evalRPN(tokens))
tokens = []string{"4", "13", "5", "/", "+"}
fmt.Println(evalRPN(tokens))
tokens = []string{"10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"}
fmt.Println(evalRPN(tokens))
}
代码2: DFS 递归
package main
import (
"fmt"
"strconv"
)
func evalRPN(tokens []string) int {
var dfs func() int
dfs = func() int {
if len(tokens) == 0 {
return 0
}
op := tokens[len(tokens)-1]
tokens = tokens[:len(tokens)-1]
if op == "+" {
return dfs() + dfs()
} else if op == "-" {
a, b := dfs(), dfs()
return b - a
} else if op == "*" {
return dfs() * dfs()
} else if op == "/" {
a, b := dfs(), dfs()
return b / a
} else {
num, _ := strconv.Atoi(op)
return num
}
}
return dfs()
}
func main() {
tokens := []string{"2", "1", "+", "3", "*"}
fmt.Println(evalRPN(tokens))
tokens = []string{"4", "13", "5", "/", "+"}
fmt.Println(evalRPN(tokens))
tokens = []string{"10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"}
fmt.Println(evalRPN(tokens))
}
输出:
9
6
22
🌟 每日一练刷题专栏 🌟
✨ 持续,努力奋斗做强刷题搬运工!
👍 点赞,你的认可是我坚持的动力!
🌟 收藏,你的青睐是我努力的方向!
✎ 评论,你的意见是我进步的财富!
☸ 主页:https://hannyang.blog.csdn.net/
Golang每日一练 专栏 | |
Python每日一练 专栏 | |
C/C++每日一练 专栏 | |
Java每日一练 专栏 |