第8周

2021-11-20
9分钟阅读时长

第8周 第16课 | 位运算

1. 位运算基础及实战要点

参考链接

如何从十进制转换为二进制

2. 位运算实战题目解析

参考链接

N 皇后位运算代码示例

def totalNQueens(self, n): 
	if n < 1: return [] 
	self.count = 0 
	self.DFS(n, 0, 0, 0, 0) 
	return self.count

def DFS(self, n, row, cols, pie, na): 
	# recursion terminator 
	if row >= n: 
		self.count += 1 
		return

	bits = (~(cols | pie | na)) & ((1 << n) — 1)  # 得到当前所有的空位

	while bits: 
		p = bits & —bits # 取到最低位的1
		bits = bits & (bits — 1) # 表示在p位置上放入皇后
		self.DFS(n, row + 1, cols | p, (pie | p) << 1, (na | p) >> 1) 
        # 不需要revert  cols, pie, na 的状态
class Solution {
	private int size; 
	private int count;

	private void solve(int row, int ld, int rd) { 
		if (row == size) { 
			count++; 
			return; 
		}
		int pos = size & (~(row | ld | rd)); 
		while (pos != 0) { 
			int p = pos & (-pos); 
			pos -= p; // pos &= pos - 1; 
			solve(row | p, (ld | p) << 1, (rd | p) >> 1); 
		} 
	} 

public int totalNQueens(int n) { 
	count = 0; 
	size = (1 << n) - 1; 
	solve(0, 0, 0); 
	return count; 
  } 
}
def solveNQueens(self, n):
  def DFS(queens, xy_dif, xy_sum):
    p = len(queens)
    if p==n:
        result.append(queens)
        return None
    for q in range(n):
        if q not in queens and p-q not in xy_dif and \
          p+q not in xy_sum: 
            DFS(queens+[q], xy_dif+[p-q], xy_sum+[p+q])  
  result = []
  DFS([],[],[])
  return [ ["."*i + "Q" + "."*(n-i-1) for i in sol] for sol in result]

实战题目 / 课后作业

191. 位1的个数

class Solution {
    /**
     * 位运算
     * @param Integer $n
     * @return Integer
     */
    function hammingWeight($n) {
        $cnt = 0;
        while ($n > 0) {
            $cnt++;
            $n &= $n - 1;
        }
        return $cnt;
    }
    
    function hammingWeight($n) {
        $cnt = 0;
        while ($n > 0) {
            $cnt += $n & 1;
            $n = $n >> 1;
        }
        return $cnt;
    }
    
    function hammingWeight($n) {
        $count = 0;
        $mask = 1;
        for($i=0; $i<32; $i++) {
            if ($n & $mask) {
                $count ++;
            }
            $mask = $mask << 1;
        }
        return $count;
    }
}

231. 2的幂

class Solution {

    /**
     * @param Integer $n
     * @return Boolean
     */
    function isPowerOfTwo($n) {
        return $n > 0 && ($n & ($n - 1)) == 0;
        //return ($n > 0) && ($n & -$n) == $n;
    }
}

190. 颠倒二进制位

class Solution {
    /**
     * @param Integer $n
     * @return Integer
     */
    function reverseBits($n) {
        $ret = 0;
        $power = 31;
        while ($ret > 0) {
            $ret += ($n & 1) << $power;
            $n = $n >> 1;
            $power -= 1;
        }
        return $res;
    }
}

51. N皇后

class Solution {
    private $res = [];
    private $count = 0;
    /**
     * @param Integer $n
     * @return String[][]
     */
    function solveNQueens($n) {
        if ($n < 1) return 0;
        $this->dfs($n, 0, 0, 0, 0, []);
        return $this->res;
    }
    function dfs($n, $row, $cols, $pie, $na, $curr_state) {
        if ($n <= $row) {
            $res = [];
            foreach ($curr_state as $col) {
                for ($j = 0; $j < $n; $j++) {
                    if ($col & (1 << $j)) {
                        $col = $j;
                        break;
                    }
                }
                $res[] = str_pad('', $col, '.') . 'Q' . str_pad('', $n - $col - 1, '.');
            }
            $this->res[] = $res;
            $this->count++;
            return;
        }
        $bits = (~($cols | $pie | $na)) & ((1 << $n) - 1);
        while ($bits) {
            $p = $bits & -$bits;
            $curr_state[] = $p;  //这里存在bug, 请大佬指出哪里,应该怎么写
            $this->dfs($n, $row + 1, $cols | $p, ($pie | $p) << 1, ($na | $p) >> 1, $curr_state);
            array_pop($curr_state);
            $bits = $bits & ($bits - 1);
        }
    }
}

52. N皇后 II

class Solution {
	private $count = 0;
    /**
     * @param Integer $n
     * @return Integer
     */
    function totalNQueens($n) {
        if ($n < 1) return 0;
        $this->dfs($n, 0, 0, 0, 0);
        return $this->count;
    }
    function dfs($n, $row, $col, $pie, $na) {
        if ($n == $row) {
            $this->count++;
            return;
        }
        $bits = (~($col | $pie | $na)) & ((1 << $n)) - 1);//得到所有的空位
        while ($bits) {
            $p = $bits & -$bits; //获取最后一位1
            $bits &= ($bits - 1); 
            $this->dfs($n, $row + 1, $col | $p, ($pie | $p) << 1, ($na | $p) >> 1);
        }
    }
}

338. 比特位计数

class Solution {

    /**
     * @param Integer $num
     * @return Integer[]
     */
    function countBits($num) {
        $dp = array_fill(0, $num + 1; 0);
        for ($i = 1; $i <= $num; $i++) {
            $dp[$i] = $dp[$i & ($i - 1)] + 1;
        }
        return $dp;
    }
}
// $dp[$i] = $dp[$i >> 1] + ($i&1);

第8周 第17课 | 布隆过滤器和LRU缓存

1. 布隆过滤器的实现及应用

参考链接

布隆过滤器的原理和实现

使用布隆过滤器解决缓存击穿、垃圾邮件识别、集合判重

布隆过滤器 Python 代码示例

布隆过滤器 Python 实现示例

高性能布隆过滤器 Python 实现示例

布隆过滤器 Java 实现示例 1

布隆过滤器 Java 实现示例 2

2. LRU Cache的实现、应用和题解

参考链接

Understanding the Meltdown exploit

替换算法总揽

LRU Cache Python 代码示例

class LRUCache(object): 

	def __init__(self, capacity): 
		self.dic = collections.OrderedDict() 
		self.remain = capacity

	def get(self, key): 
		if key not in self.dic: 
			return -1 
		v = self.dic.pop(key) 
		self.dic[key] = v   # key as the newest one 
		return v 

	def put(self, key, value): 
		if key in self.dic: 
			self.dic.pop(key) 
		else: 
			if self.remain > 0: 
				self.remain -= 1 
			else:   # self.dic is full
				self.dic.popitem(last=False) 
		self.dic[key] = value

实战题目 / 课后作业

146. LRU缓存机制

class LRUCache {
    private $capacity;
    private $map = [];
    private $head = null;
    private $tail = null;

    /**
     * @param Integer $capacity
     */
    function __construct($capacity) {
        $this->capacity = $capacity;
        $this->head = new DictNode('head',0);
        $this->tail = new DictNode('end',0);
        $this->head->next =  $this->tail;
        $this->tail->pre = $this->head;
    }

    /**
     * @param Integer $key
     * @return Integer
     */
    function get($key) {
        $result = -1;
        if (array_key_exists($key,$this->map)){
            $node = $this->map[$key];
            $result = $node->value;
            $this->move_node_to_head($node);
        }
        return $result;
    }

    /**
     * @param Integer $key
     * @param Integer $value
     * @return NULL
     */
    function put($key, $value) {
        if (array_key_exists($key,$this->map)){
            $node = $this->map[$key];
            $node->value = $value;
            $this->move_node_to_head($node);
        } else {
            $node = new DictNode($key,$value);
            $this->map[$key] = $node;
            $firstNode = $this->head->next;
            $firstNode->pre = $node;
            $this->head->next = $node;
            $node->next = $firstNode;
            $node->pre = $this->head;
        }
        if (count($this->map) > $this->capacity){
            $lastNode = $this->tail->pre;
            $lastSecondNode = $this->tail->pre->pre;
            $this->tail->pre = $lastSecondNode;
            $lastSecondNode->next = $this->tail;
            unset($this->map[$lastNode->key]);
        }

    }
    function move_node_to_head($node){
        $preNode = $node->pre;
        $nextNode = $node->next;
        $preNode->next = $nextNode;
        $nextNode->pre = $preNode;
        $firstNode = $this->head->next;
        $firstNode->pre = $node;
        $this->head->next = $node;
        $node->next = $firstNode;
        $node->pre = $this->head;
    }
}
class DictNode {
    public $value;
    public $key;
    public $pre = null;
    public $next = null;

    public function __construct($key,$value)
    {
        $this->key = $key;
        $this->value = $value;
    }
}

第8周 第18课 | 排序算法

1. 初级排序和高级排序的实现和特性

参考链接

十大经典排序算法

快速排序代码示例

归并排序代码示例

堆排序代码示例

课后作业

用自己熟悉的编程语言,手写各种初级排序代码

2. 特殊排序及实战题目详解

参考链接

十大经典排序算法

常见的9种排序java

9 种经典排序算法可视化动画

6 分钟看完 15 种排序算法动画展示

实战题目 / 课后作业

1122. 数组的相对排序

class Solution {

    /**
     * 方法一:计数排序
     * @param Integer[] $arr1
     * @param Integer[] $arr2
     * @return Integer[]
     */
    function relativeSortArray1($arr1, $arr2) {
        $arr = array_fill(0, 1001, 0);
        foreach ($arr1 as $num) {
            $arr[$num]++;
        }
        $res = [];
        foreach ($arr2 as $num) {
            while ($arr[$num]) {
                $res[] = $num;
                $arr[$num]--;
            }
        }
        for ($i = 0; $i <= 1001; $i++) {
            while ($arr[$i]) {
                $res[] = $i;
                $arr[$i]--;
            }
        }
        return $res;
    }

    //方法二
    function relativeSortArray($arr1, $arr2) {
        $arr = array_count_values($arr1);
        $res = [];
        foreach ($arr2 as $num) {
            while ($arr[$num]) {
                $res[] = $num;
                $arr[$num]--;
            }
            unset($arr[$num]);
        }
        ksort($arr);
        foreach ($arr as $num => $count) {
            while ($count) {
                $res[] = $num;
                $count--;
            }
        }
        return $res;
    }
}

242. 有效的字母异位词

class Solution {

    /**
     * 方法一:哈希表
     * @param String $s
     * @param String $t
     * @return Boolean
     */
    function isAnagram1($s, $t) {
        $len = strlen($s);
        if ($len != strlen($t)) return false;
        $map = [];
        for ($i = 0; $i < $len; $i++) {
            if (!isset($map[$s[$i]])) $map[$s[$i]] = 0;
            if (!isset($map[$t[$i]])) $map[$t[$i]] = 0;
            $map[$s[$i]]++;
            $map[$t[$i]]--;
        }
        foreach ($map as $c) {
            if ($c) return false; 
        }
        return true;
    }

    //方法二:统计字母出现的次数比较
    function isAnagram2($s, $t) {
        return count_chars($s, 1) == count_chars($t, 1);
    }

    /**
     * 方法三:排序比较
     * @param String $s
     * @param String $t
     * @return Boolean
     */
    function isAnagram($s, $t) {
        $s = str_split($s);
        $t = str_split($t);
        sort($s);
        sort($t);
        return $s == $t;
    }
}

1244. Design A Leaderboard 解题思路分析

https://hwchang0417.wordpress.com/2019/11/04/leetcode-1244-design-a-leaderboard/

题目说明地址

class Leaderboard {
public:
    map<int, int> m;
    Leaderboard() {}
    
    void addScore(int playerId, int score) {
        m[playerId] += score;
    }
    
    int top(int K) {
        int sum = 0;
        priority_queue<int, std::vector<int>, std::greater<int>> pq;
        for(pair<int, int> p : m){
            sum += p.second;
            pq.push(p.second);
            if(pq.size() > K){
                sum -= pq.top();
                pq.pop();
            }
        }
        return sum;
    }
    
    void reset(int playerId) {
        m.erase(m.find(playerId));
    }
};

56. 合并区间

class Solution {

    /**
     * @param Integer[][] $intervals
     * @return Integer[][]
     */
    function merge($intervals) {
        //排序
        array_multisort(array_column($intervals, 0), $intervals);
        $res = [];
        $i = -1;
        foreach ($intervals as $interval) {
            if ($i == -1 || $res[$i][1] < $interval[0]) {
                $res[++$i] = $interval;
            } else {
                $res[$i][1] = max($res[$i][1], $interval[1]);
            }
        }
        return $res;
    }
}

493. 翻转对

class Solution {

    /**
     * @param Integer[] $nums
     * @return Integer
     */
    function reversePairs($nums) {
        return $this->mergesort($nums, 0, count($nums) - 1);
        return $this->mergesort_and_count($nums, 0, count($nums) - 1);
    }

    /**
     * 参考链接
     * https://leetcode.com/problems/reverse-pairs/discuss/97306
     * @param [type] $nums
     * @param [type] $start
     * @param [type] $end
     * @return int
     */
    function mergesort(&$nums, $start, $end) {
        if ($start >= $end) return 0;
        $mid = $start + (($end - $start) >> 1);
        $count = $this->mergesort($nums, $start, $mid) + $this->mergesort($nums, $mid + 1, $end);
        $cache = [];
        $i = $t = $start;
        $c = 0;
        for ($j = $mid + 1; $j <= $end; $j++, $c++) {
            while ($i <= $mid && $nums[$i] <= 2 * $nums[$j]) $i++;
            while ($t <= $mid && $nums[$t] < $nums[$j]) $cache[$c++] = $nums[$t++];
            $cache[$c] = $nums[$j];
            $count += $mid - $i + 1;
        }
        while ($t <= $mid) $cache[$c++] = $nums[$t++];
        for ($i = 0; $i < $c; $i++) {
            $nums[$start + $i] = $cache[$i];
        } 
        return $count;
    }

    function mergesort_and_count(&$nums, $start, $end) {
        if ($start >= $end) return 0;
        $mid = $start + (($end - $start) >> 1);
        $count = $this->mergesort_and_count($nums, $start, $mid) + $this->mergesort_and_count($nums, $mid + 1, $end);
        $j = $mid + 1;
        for ($i = $start; $i <= $mid; $i++) {
            while ($j <= $end && $nums[$i] > $nums[$j] * 2) $j++;
            $count += $j - ($mid + 1);
        }
        $this->merge($nums, $start, $mid, $end);
        return $count;
    }

    function merge(&$nums, $start, $mid, $end) {
        $n1 = $mid - $start + 1;
        $n2 = $end - $mid;
        $l = $r = [];
        for ($i = 0; $i < $n1; $i++) $l[$i] = $nums[$start + $i];
        for ($i = 0; $i < $n2; $i++) $r[$i] = $nums[$mid + 1 + $i];
        for ($i = 0, $j = 0, $k = $start; $k <= $end; $k++) {
            if ($j >= $n2 || ($i < $n1 && $l[$i] < $r[$j])) {
                $nums[$k] = $l[$i++];
            } else {
                $nums[$k] = $r[$j++];
            }
        }
    }
}

本周作业

简单

191. 位1的个数

231. 2的幂

190. 颠倒二进制位

用自己熟悉的编程语言,手写各种初级排序代码,提交到第 8 周学习总结中。

1122. 数组的相对排序

242. 有效的字母异位词

中等

242. 有效的字母异位词

https://leetcode-cn.com/problems/design-a-leaderboard/

56. 合并区间

困难

51. N皇后

52. N皇后 II

493. 翻转对

下周预习

预习知识点

预习题目

上一页 第7周
下一页 第9周