1 题号:902 小于n的最大数
1.1 题目
- 给一个按非递减排列的整数数组,给定一个n值,用这个数组中的值来组合不大于n的最大值,数组中元素可以重复使用
1.2 思路:
- 先把数组从大到小排序,然后从中选取数字来组成数字,
- 这里有个问题:如果n中有数小于nums中的最小值,那么就不应该再在同位置上num是 > n中对应位的时候跳过了
1.3 go实现:
func maxValueLessThanN(nums []int, n int) int {
sort.Slice(nums, func(i, j int) bool { return nums[i] > nums[j] })
res := -1
digits := getDigits(n)
var backtrack func(curIdx, curNum int, digitSameToNum bool)
backtrack = func(curIdx, curNum int, digitSameToNum bool) {
if curIdx == len(digits) {
if curNum <= n {
res = max(curNum, res)
}
return
}
digit := digits[curIdx]
for _, num := range nums {
if digitSameToNum && num > digit {
continue
}
curNum = curNum*10 + num
backtrack(curIdx+1, curNum, digit == num)
}
}
backtrack(0, 0, true)
return res
}
func getDigits(n int) []int {
digits := []int{}
for n > 0 {
digits = append([]int{n % 10}, digits...)
n = n / 10
}
return digits
}
func TmaxValueLessThanN() {
nums := []int{4, 2, 5, 7}
n := 67921
fmt.Println(maxValueLessThanN(nums, n))
}
1.4 总结:
- 注意当digit和num不等的时候就可以在nums中任意选了,因为是nums是从大到小排列的,所以任意选就是选最大的
2 题号:415 大数相加
2.1 题目
2.2 思路:
- 用i和j指向两个字符串的最后一个字符,用carry表示是否有进位
- 只要i和j中有一个 >=0或者有进位,就可以继续遍历
2.3 go实现:
func addStrings(num1 string, num2 string) string {
carray := 0
res := ""
for i,j := len(num1)-1, len(num2)-1;i >= 0 || j>= 0|| carray != 0;i,j = i - 1, j-1{
var n1 , n2 int
if i >= 0{
n1 = int(num1[i] - '0')
}
if j >= 0{
n2 = int(num2[j] - '0')
}
intRes := n1 + n2 + carray
carray = intRes / 10
res = strconv.Itoa(intRes % 10) + res
}
return res
}
2.4 总结:
- go中字符串中一个字符减去一个字符的值不是int类型,需要转成int
3 题号:192 字符串转数字
3.1 题目
- 给定一个字符串转成数字,字符串中只有数字、大小写字母、正负号和下划线,如果超出int32的最大数就返回int32的最大数
3.2 思路:
- 先把前导空格去掉
- 用一个变量保存符号
- 从前到后遍历排除其他字符保留数字
3.3 go实现:
func myAtoi(str string) int {
str = strings.TrimSpace(str)
res := 0
sign := 1
for i, v := range str {
if i == 0 && v == '+' {
sign = 1
} else if i == 0 && v == '-' {
sign = -1
} else if int(v - '0') >= 0 && int(v -'0')<= 9{
res = res*10 + int(v-'0')
}else{
break
}
if res > math.MaxInt32 {
if sign == 1 {
return math.MaxInt32
} else {
return math.MinInt32
}
}
}
return res * sign
}
3.4 总结:
题号:链表排序
题目
思路:
- 归并排序,链表从前到后,先把一个节点当做一个链表,两两排序,然后两个节点当做一个链表排序
go实现:
func merge(head1, head2 *ListNode)*ListNode{
dummyHead := &ListNode{}
cur := dummyHead
for head1 != nil && head2 != nil{
if head1.Val < head2.Val{
cur.Next = head1
head1 = head1.Next
}else{
cur.Next = head2
head2 = head2.Next
}
cur = cur.Next
}
if head1 != nil{
cur.Next = head1
}
if head2 != nil{
cur.Next = head2
}
return dummyHead.Next
}
func sortList(head *ListNode) *ListNode {
if head == nil{
return head
}
listLen := 0
for cur := head; cur != nil; cur = cur.Next{
listLen++
}
dummyHead := &ListNode{Next: head}
for curLen := 1; curLen < listLen; curLen = curLen*2{
prev, cur := dummyHead, dummyHead.Next
for cur != nil{
head1 := cur
for i := 1; i < curLen && cur.Next != nil; i++{
cur = cur.Next
}
head2 := cur.Next
cur.Next = nil
cur = head2
for i := 1; i < curLen && cur != nil && cur.Next != nil;i++{
cur = cur.Next
}
var next *ListNode
if cur != nil{
next = cur.Next
cur.Next = nil
}
prev.Next = merge(head1, head2)
for prev.Next != nil{
prev = prev.Next
}
cur = next
}
}
return dummyHead.Next
}
总结:
- 对每一个节点要清晰:拆分链表、记录每一轮的prev,next
题号:146 lru
题目
思路:
go实现:
type Node struct{
key int
val int
pre *Node
next *Node
}
type LRUCache struct {
head *Node
tail *Node
size int
cap int
hash map[int]*Node
}
func Constructor(capacity int) LRUCache {
hash := make(map[int]*Node)
head := &Node{}
tail := &Node{}
lru := LRUCache{
head:head,
tail:tail,
hash:hash,
cap:capacity,
size:0,
}
lru.head.next = lru.tail
lru.tail.pre = lru.head
return lru
}
func (this *LRUCache)addAtHead(node *Node){
node.pre = this.head
node.next = this.head.next
this.head.next.pre = node
this.head.next = node
}
func (this *LRUCache)moveToHead(node *Node){
node.next.pre = node.pre
node.pre.next = node.next
this.addAtHead(node)
}
func (this *LRUCache)removeTail(){
delete(this.hash, this.tail.pre.key)
this.tail.pre.pre.next = this.tail
this.tail.pre = this.tail.pre.pre
this.size--
}
func (this *LRUCache) Get(key int) int {
if v, exists := this.hash[key]; !exists{
return -1
}else{
this.moveToHead(v)
return v.val
}
}
func (this *LRUCache) Put(key int, value int) {
if v, exists := this.hash[key];!exists{
if this.size == this.cap{
this.removeTail()
}
newNode := &Node{key:key, val:value}
this.hash[key] = newNode
this.addAtHead(newNode)
this.size++
}else{
v.val = value
this.moveToHead(v)
}
}
总结: