Dongxing's Wiki Dongxing's Wiki
首页
  • 剑指 Offer
  • LeetCode
  • 算法与数据结构
  • Python 语言
  • Web 开发
  • Hive
  • Elastic Search
  • 机器学习
  • NLP
  • 检索技术
  • 数据分析
  • 经验笔记
  • Linux 配置
  • 博客进化记
  • 杂谈
GitHub (opens new window)
首页
  • 剑指 Offer
  • LeetCode
  • 算法与数据结构
  • Python 语言
  • Web 开发
  • Hive
  • Elastic Search
  • 机器学习
  • NLP
  • 检索技术
  • 数据分析
  • 经验笔记
  • Linux 配置
  • 博客进化记
  • 杂谈
GitHub (opens new window)
  • LeetCode

    • Leetcode 题解目录导航
    • Leetcode题解(1)- Easy
    • Leetcode题解(2)- Easy
    • Leetcode题解(3)- Easy
    • Leetcode题解(4)- Easy
    • Leetcode题解(5)- 2018 力扣 Leetcode CN 高频题汇总 part 1 字符串
    • Leetcode题解(6)- 2018 力扣 Leetcode CN 高频题汇总 part 2 数组
    • Leetcode题解(7)- 2018 力扣 Leetcode CN 高频题汇总 part 3 堆、栈、队列、链表
    • Leetcode题解(8)- 2018 力扣 Leetcode CN 高频题汇总 part 4 哈希与映射、树
    • Leetcode题解(9)- 2018 力扣 Leetcode CN 高频题汇总 part 5 排序检索、动态规划
    • Leetcode题解(10)- 2018 力扣 Leetcode CN 高频题汇总 part 6 图论
    • Leetcode题解(11)- 2018 力扣 Leetcode CN 高频题汇总 part 7 数学&位运算
    • Leetcode题解(12)- 2018 力扣 Leetcode CN 高频题汇总 part 8
      • 快乐数
        • 问题
        • 思路
        • 代码
      • 两整数之和
        • 问题
        • 思路
        • 代码
      • Fizz Buzz
        • 问题
        • 代码
      • 加油站
        • 问题
        • 思路
        • 代码
      • LRU 缓存机制
        • 问题
        • 思路
        • 代码
    • Leetcode (13) - Hot 100 热门 100 题
    • Leetcode (14) - Hot 100 热门 100 题
  • LeetCode
  • LeetCode
anthony
2019-06-18
目录

Leetcode题解(12)- 2018 力扣 Leetcode CN 高频题汇总 part 8

# 快乐数

Leetcode 202 题

# 问题

编写一个算法来判断一个数是不是“快乐数”。

一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。

示例: 
输入: 19
输出: true

解释: 
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
1
2
3
4
5
6
7
8
9

# 思路

按题目要求来循环计算快乐数吧,同时把之前的结果存下来,当发现有重复出现的数字时,说明不是快乐数,出现无限循环了。

# 代码

class Solution(object):
    def isHappy(self, n):
        already = set()
        
        while n != 1:
            num = 0
            while n > 0:
                tmp = n % 10
                num += tmp**2
                n //= 10
            if num in already:
                return False
            else:
                already.add(num)
            n = num
        return True
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 两整数之和

Leetcode 371题

# 问题

不使用运算符 + 和 - ,计算两整数a b之和。

# 思路

那就位运算吧。位运算的 xor 相当于做了无进位的加法,比如说 0101 和 0100 做xor后得到 0001。而与运算相当于做了加法的进位,例如 0101 和 0100 做与运算后得到 0100 需要再左移一位变成 1000 这就是加法的进位。

按说接下来把 0001 和1000 相加就完成了,但是不能用加法,那其实目前就是把原来 0101 和 0100 的加法,转换成了 0001 和 1000 的加法了。所以继续重复 xor 和 与 运算,直到进位变成0,这时意味着不再需要进位了, 得到的无进位值就是最终结果。

# 代码

python中的特殊处理 在 Python 中,整数不是 32 位的,也就是说你一直循环左移并不会存在溢出的现象,这就需要我们手动对 Python 中的整数进行处理,手动模拟 32 位 INT 整型。

具体做法是将整数对 0x100000000 取模,保证该数从 32 位开始到最高位都是 0。

class Solution(object):
    def getSum(self, a, b):
        """
        :type a: int
        :type b: int
        :rtype: int
        """
        # 2^32
        MASK = 0x100000000
        # 整型最大值
        MAX_INT = 0x7FFFFFFF
        MIN_INT = MAX_INT + 1
        while b != 0:
            # 计算进位
            carry = (a & b) << 1 
            # 取余范围限制在 [0, 2^32-1] 范围内
            a = (a ^ b) % MASK
            b = carry % MASK
        return a if a <= MAX_INT else ~((a % MIN_INT) ^ MAX_INT)   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

感觉python不适合搞二进制 hhhhhh

# Fizz Buzz

Leetcode 412题

# 问题

写一个程序,输出从 1 到 n 数字的字符串表示。

  1. 如果 n 是3的倍数,输出“Fizz”;
  2. 如果 n 是5的倍数,输出“Buzz”; 3.如果 n 同时是3和5的倍数,输出 “FizzBuzz”。
示例:
n = 15,
返回:
[
    "1",
    "2",
    "Fizz",
    "4",
    "Buzz",
    "Fizz",
    "7",
    "8",
    "Fizz",
    "Buzz",
    "11",
    "Fizz",
    "13",
    "14",
    "FizzBuzz"
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 代码

class Solution(object):
    def fizzBuzz(self, n):
        ret = []
        for i in range(1, n+1):
            fizz = i % 3 == 0
            buzz = i % 5 == 0
            if fizz and buzz:
                ret.append('FizzBuzz')
            elif fizz:
                ret.append('Fizz')
            elif buzz:
                ret.append('Buzz')
            else:
                ret.append(str(i))
        return ret
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 加油站

Leetcode 134题

# 问题

在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。

说明:  如果题目有解,该答案即为唯一答案。 输入数组均为非空数组,且长度相同。 输入数组中的元素均为非负数。

示例 1:

输入: 
gas  = [1,2,3,4,5]
cost = [3,4,5,1,2]
输出: 3

解释:
从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油
开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油
开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油
开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油
开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油
开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。
因此,3 可为起始索引。

示例 2:

输入: 
gas  = [2,3,4]
cost = [3,4,3]
输出: -1

解释:
你不能从 0 号或 1 号加油站出发,因为没有足够的汽油可以让你行驶到下一个加油站。
我们从 2 号加油站出发,可以获得 4 升汽油。 此时油箱有 = 0 + 4 = 4 升汽油
开往 0 号加油站,此时油箱有 4 - 3 + 2 = 3 升汽油
开往 1 号加油站,此时油箱有 3 - 3 + 3 = 3 升汽油
你无法返回 2 号加油站,因为返程需要消耗 4 升汽油,但是你的油箱只有 3 升汽油。
因此,无论怎样,你都不可能绕环路行驶一周。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 思路

首先可以明确,如果 sum(gas) 比 sum(cost) 小,那肯定是不能完成的,如果大于等于的话,则是一定可以完成的.

所以开始遍历,用total来累计gas和cost,最后如果total小于0说明不能完成;用tank表示当前油箱的油,如果在某个点tank小于0了,则tank重置为0并标记这个点为起始点,用 gas[i]-cost[i] 来更新tank。

# 代码

class Solution(object):
    def canCompleteCircuit(self, gas, cost):
        tank, total = 0, 0
        start = 0
        for i in range(len(gas)):
            total += gas[i] - cost[i]
            if tank < 0:
                tank = gas[i] - cost[i]
                start = i
            else:
                tank += gas[i] - cost[i]
        return start if total >= 0 else -1
1
2
3
4
5
6
7
8
9
10
11
12

# LRU 缓存机制

leetcode 146题

# 问题

运用你所掌握的数据结构,设计和实现一个  LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。

获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。

写入数据 put(key, value) - 如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。

你是否可以在 O(1) 时间复杂度内完成这两种操作?

示例:
LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // 返回  1
cache.put(3, 3);    // 该操作会使得密钥 2 作废
cache.get(2);       // 返回 -1 (未找到)
cache.put(4, 4);    // 该操作会使得密钥 1 作废
cache.get(1);       // 返回 -1 (未找到)
cache.get(3);       // 返回  3
cache.get(4);       // 返回  4
1
2
3
4
5
6
7
8
9
10
11
12

# 思路

所使用的数据结构如下图所示:

使用哈希表来进行 k v 的访问,实现快速的get操作。通过双向链表及指针操作,快速实现将某个最近访问过的节点,移动到链表尾部。

具体参照下面的代码。最重要的就是要知道LRU可以用这种数据结构来实现,这样可以O(1)的来完成查找和插入操作。具体的则是代码实现时的一些细节要注意,包括链表改指针的先后顺序啦等等。

# 代码

class ListNode(object):
    def __init__(self, key=None, value=None):
        self.key = key
        self.value = value
        self.prev = None
        self.next = None
        

class LRUCache(object):

    def __init__(self, capacity):
        self.capacity = capacity
        self.hashmap = {}
        # 空的头尾节点
        self.head = ListNode()
        self.tail = ListNode()
        self.head.next = self.tail
        self.tail.prev = self.head
    
    
    # 将给定key的节点移动到尾部
    def move_to_tail(self, key):
        # 获取节点
        node = self.hashmap[key]
        # 将节点从原来位置删除
        node.prev.next = node.next
        node.next.prev = node.prev
        # 将节点追加到空的tail节点之前
        node.prev = self.tail.prev
        node.next = self.tail
        self.tail.prev.next = node
        self.tail.prev = node
        

    def get(self, key):
        # 节点存在,则读取,并移至末尾表示最近更新过
        if key in self.hashmap:
            self.move_to_tail(key)
        node = self.hashmap.get(key, None)
        if node:
            return node.value
        else:
            return -1
        

    def put(self, key, value):
        # 节点存在
        if key in self.hashmap:
            # 需要注意,值可能会更新
            self.hashmap[key].value = value
            # 移至末尾,表示最近更新过
            self.move_to_tail(key)
        else:
            # 容量超限
            if len(self.hashmap) == self.capacity:
                # 删除头部的节点
                self.hashmap.pop(self.head.next.key)
                self.head.next = self.head.next.next
                self.head.next.prev = self.head
            # 新建节点
            new = ListNode(key, value)
            self.hashmap[key] = new
            # 新节点放在尾部
            new.prev = self.tail.prev
            new.next = self.tail
            self.tail.prev.next = new
            self.tail.prev = new
        

# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

太棒啦~ 力扣 2018 高频题这个专题,终于完成啦~~ 完结撒花!

接下来做一下力扣里的 热题 100 、 精选 TOP 面试题 、腾讯50题 这几个专题吧,当然很多题目是已经做过了的就不再重复刷。看上去大概还需要再做六七十题的样子。

上次更新: 2022/11/11, 2:11:00
Leetcode题解(11)- 2018 力扣 Leetcode CN 高频题汇总 part 7 数学&位运算
Leetcode (13) - Hot 100 热门 100 题

← Leetcode题解(11)- 2018 力扣 Leetcode CN 高频题汇总 part 7 数学&位运算 Leetcode (13) - Hot 100 热门 100 题→

Theme by Vdoing | Copyright © 2017-2023 anthony 京ICP备17072417-3
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式