数据结构和算法


1  (num & (~num + 1)) 获取num 第一个二进制位为1的数

    12
    1100     2**3 + 2**2 + .. => 12

    print( 12 & (~12 + 1)) 
    # 0100  2**2 4 

2   l + ((r - l) >> 1) 获取 left , right 中的中位数 
            
    l = 1
    r = 11
    
    origin = ""
    for i in range(l, r + 1):
        origin += str(i)
    
    print(origin)
    # 1 2 3 4 5    6   7 8 9 10 11
    print(l + ((r - l) >> 1))

3   (1 << n) -1 获取 2的N次方 - 1    (2 ** n - 1)


4   int 32位 n (n >> 31)
     负数 得到 1
     正数 得到 0

数组中出现次数超过一半的数字


# 1 字典映射

from collections import defaultdict

count_dict = defaultdict(int)
l = [1, 0, 1, 3, 5, 1, 4, 1, 1, 1]

def find_max_len(l):
    for item in l:
        count_dict[item] += 1
        if count_dict[item] * 2 > len(l):
            return item 
    
print(find_max_len(l))


# 2 摩尔投票
def moor_select(nums):
    count = 0
    majority = 0
    # 摩尔投票法
    for num in nums:
        if count == 0:
            majority = num
        count += 1 if num == majority else -1
    return majority

100 以内的质数

prime_number = []

for i in range(2, 101):
    is_prime = True
    for j in range(2, i):
        if i % j == 0:
            is_prime = False
            break
    if is_prime:
        prime_number.append(i)


print(prime_number)

数组中有一个数出现次数为奇数次, 其他均为偶数次, 求出这个数 (两个数为奇数次, 求出这两个数)

l1 = [1, 1, 2, 3, 3, 4, 5, 5, 4]
l2 = [1, 1, 2, 3, 3, 4, 5, 5, 4, 9]


class Solution:

    def __init__(self, array):
        self.array = array

    def solution_one_odd(self):
        result = 0
        #  0 与 任何数 亦或都等于这个数本身
        for number in self.array:
            # 出现偶数次的数亦或之后都是 0,最后剩下的数就是出现奇数次数的数
            result ^= number
        return result

    @staticmethod
    def _get_first_bin(number):
        return number & (~number + 1)

    def solution_two_odd(self):
        tmp_result = 0
        for number in self.array:
            tmp_result ^= number

        a = 0
        b = 0
        mask = self._get_first_bin(tmp_result)
        # 找到 tmp_result 中第一次为1的位数值
        for number in self.array:
            # 区分 该 位是否为1
            if self._get_first_bin(number) == mask:
                a ^= number
            else:
                b ^= number

        return a, b


s = Solution(array=l1)
print(s.solution_one_odd())


s = Solution(array=l2)
print(s.solution_two_odd())

无重复字符的最长子串

def find_max_length(s):
    start = 0
    max_len = 0
    tmp_dic = {}
    for index, string in enumerate(s):
        if string in tmp_dic and tmp_dic[string] >= start:
            start = tmp_dic[string] + 1
        tmp_dic[string] = index
        max_len = max(max_len, index - start + 1)
    return max_len


print(find_max_length("pwwkew3215789"))

通过 2个 5/6 升水壶 从池塘得到3升水


# 装满情况下
# 5  ==>  6
# 5  ==>  6 

# 5 得到 4

# 6 清空
# 5  ==>  6   
# 6 得到 4

# 5  ==>  6 
# 5 剩下 3

第二高的薪水 (mysql)

Employee 表:
+-------------+------+
| Column Name | Type |
+-------------+------+
| id          | int  |
| salary      | int  |
+-------------+------+
id 是这个表的主键。
表的每一行包含员工的工资信息

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/second-highest-salary
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
select (select distinct salary from Employee order by salary desc limit 1,1 ) as SecondHighestSalary
-- SELECT DISTINCT salary FROM employee ORDER BY salary DESC LIMIT N, 1 
-- 第N高的薪水
select max(salary) as SecondHighestSalary from 
Employee
where salary < (select max(salary) from Employee)

两数之和

# 1 O(N)  O(N)
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        hash_map = {}
        for index, num in enumerate(nums):
            if hash_map.get(target - num) is not None: 
                return index, hash_map.get(target - num)
            hash_map[num] = index
        
            
# 2         
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        number_length = len(nums)
        for left, tmp_num in enumerate(nums):
            right = number_length - 1
            while right > left:
                if nums[right] == target - tmp_num:
                    return left, right
                right -= 1

#  3 
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        for left, tmp_num in enumerate(nums):
            for right, tmp_num_ in enumerate(nums):
                    if tmp_num + tmp_num_ == target and left != right:
                        return left, right 

单向链表翻转

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


class Solution(object):

    def reverse_node(self, head):
        current_node, pre_node = head, None
        while current_node:
            tmp = current_node.next
            current_node.next = pre_node
            pre_node = current_node
            current_node = tmp
        return pre_node
        

    def reverse_node_(self, head):
        if not head or not head.next:
            return head
        res = self.reverse_node_(head.next)
        head.next.next = head
        head.next = None
        return res

Graph

图: 

    顶点: 顶点又称为节点,是图的基础部分,我们可以给它一个名字叫“键”。

    边:   边是图的另一个基础部分,两个顶点通过一条边相连,表示它们之间存在的关系,边既可以是单向的也可以是双向的

    权重:  边可以带权重,表示从一个顶点到另一个顶点的成本

    路径:   路径是由边连接的顶点组成的序列

    环:    有向图中的一条起点和终点为同一顶点的路径,没有环的图叫无环图,没有环的有向图叫有向无环图(DAG)

图的表示

邻接表法:对于每个图中的点,将它的邻居放到一个链表里

邻接矩阵:对于 n 个点,构造一个 n * n 的矩阵,如果有从点 i 到点 j 的边,就将矩阵的位置 matrix[i][j] 置为 1.

图的遍历

BFS: Breadth First Search,广度优先搜索

DFS: Depdth First Search,深度优先搜索

# 图的广度优先遍历
from queue import Queue

GRAPH = {
    'A': ['B', 'F'],
    'B': ['C', 'I', 'G'],
    'C': ['B', 'I', 'D'],
    'D': ['C', 'I', 'G', 'H', 'E'],
    'E': ['D', 'H', 'F'],
    'F': ['A', 'G', 'E'],
    'G': ['B', 'F', 'H', 'D'],
    'H': ['G', 'D', 'E'],
    'I': ['B', 'C', 'D'],
}

q = Queue()
unique_set = set()

#
def bfs(graph, start):
    q.put(start)
    while not q.empty():
        current = q.get()
        if current not in unique_set:
            unique_set.add(current)
            print(current)
            for next in graph[current]:
                q.put(next)


bfs(GRAPH, 'A')

# A
# B
# F
# C
# I
# G
# E
# D
# H

#
def dfs(graph, start):
    if start not in unique_set:
        print(start)
        unique_set.add(start)
    for next in graph[start]:
        if next not in unique_set:
            dfs(graph, next)


dfs(GRAPH, 'A')

# 
# A
# B
# C
# I
# D
# G
# F
# E
# H

####

Buy me a 肥仔水!