实战题目

3 阅读3分钟

1. 小于n的最大数(字节真题)

题目要求:给定一个数n如23121;给定一组数字a如[2 4 9]求由a中元素组成的小于n的最大数

思路:来自这里

先按目标数N的位数从高位到低位找,如果在数组中能找到与某位数相等的数,则将其推进数组,如果没找到,则从数组剩余数里面挑其次,有其次就找其次,且从该位开始后面可以直接push数组中最大的数了;如果没有其次,那么说明需要回退上一位(pop),找到上一位的其次,循环直到res拿到结果,走 break 跳出循环。

func maxNumber(_ n: Int, _ set: [Int]) -> Int {
    var digits = [Int]()
    var n = n
    while n != 0 {
        digits.insert(n % 10, at: 0)
        n = n / 10
    }
    
    // 在set里面 优先找等于当前数字, 否则找次小的
    // 都不满足(set里没有比当前数 更小的数了)返回 -1
    func findSuitNum(_ n: Int) -> Int {
        for i in (0..<set.count).reversed() {
            if set[i] <= n { return set[i] }
        }
        return -1
    }
    
    var fixIndex = 0
    // 是否寻找次小数
    var findMax = true
    while fixIndex != digits.count {
        let num = digits[fixIndex]
        // 最后一位强制查询次小数
        if fixIndex == digits.count - 1 {
            findMax = false
        }
        let suitN = findSuitNum(findMax ? num : num - 1)
        findMax = true
        if suitN == -1 {
            // 没找到,则回退上一位 去找次小数
            fixIndex -= 1
            // 最高位就没找到直接break
            if fixIndex < 0 {
                break
            } else {
                findMax = false
            }
        } else if suitN == num {
            // 找到当前数,找下一位
            fixIndex += 1
        } else if suitN < num {
            // 只能找到次小数,直接退出,准备补充最大数
            digits[fixIndex] = suitN
            fixIndex += 1
            break;
        }
    }
    
    if fixIndex > 0 {
        for i in fixIndex..<digits.count {
            digits[i] = set.last!
        }
    } else {
        // 最高位最后用不了。 除了本身最高位找不到,还存在回退的情况 2111  [2, 7, 9]
        let size = digits.count
        digits.removeAll()
        for _ in 0..<(size - 1) {
            digits.append(set.last!)
        }
    }
    
    var res = 0
    for (i, num) in digits.enumerated() {
        res += num * ( pow(10, digits.count - i - 1) as NSDecimalNumber).intValue
    }
    
    return res
}

_ = maxNumber(777, [1, 4, 7]) 
// 这些case都能通过
//n=23132, a=[2,4,9], ans=22999
//n=21132, a=[2,4,9], ans=9999
//n=24132, a=[2,4,9], ans=22999
//n=24132, a=[1,4,9], ans=19999
//n=14132, a=[2,4,9], ans=9999
//n=14132, a=[1,4,9], ans=14119
//n=778, a=[1,4,7], ans=777
//n=777, a=[1,4,7], ans=774

2. LRU cache

注意使用虚拟节点,边界就会好处理很多。

class LRUCache {
    public class ListNode {
        var val: Int
        // 这里记录下key,方便删除最后一个元素
        var key = 0
        var next: ListNode?
        var pre: ListNode?
        init(_ val: Int, _ next: ListNode?, _ pre: ListNode?) {
            self.val = val
            self.next = next
            self.pre = pre
        }
        convenience init(_ val: Int) {
            self.init(val, nil, nil)
        }
    }
    let capacity: Int
    var map = [Int: ListNode]()
    let dummyHead = ListNode(0)
    var dummyLast = ListNode(0)
    var count = 0

    init(_ capacity: Int) {
        self.capacity = capacity
        dummyHead.next = dummyLast
        dummyLast.pre = dummyHead
    }
    
    func get(_ key: Int) -> Int {
        if let node = map[key] {
            // 删除链表节点
            deleteNodeInNodeList(node)
            // 插入链表头部
            insertNodeToHead(node)
            
            return node.val
        }
        return -1
    }
    
    func put(_ key: Int, _ value: Int) {
        if let node = map[key] {
            node.val = value
            // 删除链表节点
            deleteNodeInNodeList(node)
            // 插入链表头部
            insertNodeToHead(node)
        } else {
            let node = ListNode(value)
            node.key = key
            map[key] = node
            // 插入链表头部
            insertNodeToHead(node)
            // 判断移除超界限元素
            if count == capacity, let last = dummyLast.pre {
                // 删除链表节点
                deleteNodeInNodeList(last)
                map.removeValue(forKey: last.key)
            } else {
                count += 1
            }
        }
    }
    
    func deleteNodeInNodeList(_ node: ListNode) {
        node.pre?.next = node.next
        node.next?.pre = node.pre
        
        node.next = nil
        node.pre = nil
    }
    
    func insertNodeToHead(_ node: ListNode) {
        node.next = dummyHead.next
        dummyHead.next?.pre = node
        
        dummyHead.next = node
        node.pre = dummyHead
    }
}

// 持续补充