diff --git a/Week_01/MyCircularDeque.php b/Week_01/MyCircularDeque.php new file mode 100644 index 00000000..3277ddb7 --- /dev/null +++ b/Week_01/MyCircularDeque.php @@ -0,0 +1,173 @@ +capacity = $k + 1; + } + + /** + * Adds an item at the front of Deque. Return true if the operation is successful. + * @param Integer $value + * @return Boolean + */ + function insertFront($value) { + if ($this->isFull()) { + return false; + } + + if ($this->isEmpty()) { + $this->queue[$this->head] = $value; + } else { + $this->head = ($this->capacity + $this->head -1) % $this->capacity; + $this->queue[$this->head] = $value; + } + return true; + } + + /** + * Adds an item at the rear of Deque. Return true if the operation is successful. + * @param Integer $value + * @return Boolean + */ + function insertLast($value) { + if ($this->isFull()) { + return false; + } + + $this->queue[$this->tail] = $value; + $this->tail = ($this->tail + 1) % $this->capacity; + return true; + } + + /** + * Deletes an item from the front of Deque. Return true if the operation is successful. + * @return Boolean + */ + function deleteFront() { + if ($this->isEmpty()) { + return false; + } + $this->head = ($this->head + 1) % $this->capacity; + return true; + } + + /** + * Deletes an item from the rear of Deque. Return true if the operation is successful. + * @return Boolean + */ + function deleteLast() { + if ($this->isEmpty()) { + return false; + } + + $this->head = ($this->tail - 1 + $this->capacity) % $this->capacity; + return true; + } + + /** + * Get the front item from the deque. + * @return Integer + */ + function getFront() { + if ($this->isEmpty()) { + return false; + } + return $this->queue[$this->head]; + } + + /** + * Get the last item from the deque. + * @return Integer + */ + function getRear() { + if ($this->isEmpty()) { + return false; + } + + return $this->queue[$this->tail]; + } + + /** + * Checks whether the circular deque is empty or not. + * @return Boolean + */ + function isEmpty() { + return count($this->queue) == 0; + } + + /** + * Checks whether the circular deque is full or not. + * @return Boolean + */ + public function isFull() { + return $this->capacity == count($this->queue); + } +} + +/** + * Your MyCircularDeque object will be instantiated and called as such: + * $obj = MyCircularDeque($k); + * $ret_1 = $obj->insertFront($value); + * $ret_2 = $obj->insertLast($value); + * $ret_3 = $obj->deleteFront(); + * $ret_4 = $obj->deleteLast(); + * $ret_5 = $obj->getFront(); + * $ret_6 = $obj->getRear(); + * $ret_7 = $obj->isEmpty(); + * $ret_8 = $obj->isFull(); + */ + +$obj = new MyCircularDeque(10); +$ret_1 = $obj->insertFront('k4'); +$ret_11 = $obj->insertFront('k5'); +$ret_2 = $obj->insertLast('tail_001'); +$ret_3 = $obj->deleteFront(); +$ret_4 = $obj->deleteLast(); +$ret_5 = $obj->getFront(); +$ret_6 = $obj->getRear(); +$ret_7 = $obj->isEmpty(); +$ret_8 = $obj->isFull(); +var_dump($ret_1); +var_dump($ret_2); +var_dump($ret_3); +var_dump($ret_4); +var_dump($ret_5); +var_dump($ret_6); +var_dump($ret_7); +var_dump($ret_8); \ No newline at end of file diff --git a/Week_01/NOTE.md b/Week_01/NOTE.md index 50de3041..51c3df27 100644 --- a/Week_01/NOTE.md +++ b/Week_01/NOTE.md @@ -1 +1,60 @@ -学习笔记 \ No newline at end of file +【G20200343040108-Week 01】 - 学习总结 + +### 数据结构与算法的重要性 +业界最具有说明该两者重要性的一个通用公式为: + +程序 = 数据结构 + 算法 + +1. 基本概念 +算 法: 解决程序问题的流程和步骤 +数据结构: 将数据按照某种特定结构保存 + +2. 二者之间的关系 +数据结构是底层,算法高层; +数据结构为算法提供服务; +算法围绕数据结构操作 + +要想在互联网行业成为一个大牛,就必须具备非常扎实的基础,但算法与数据结构是其中的一小部分,也是不可或缺的重要部分。 +在 - 【程序设计的基础,是内功和心法】 + + +### 时间复杂度与空间复杂度分析 +#### 空间换时间 + +### 数组、链表、跳表、栈、队列、双端队列、优先队列 +#### 1. 数组的特性 +- 访问快(即:时间复杂度为O(1)) +- 删除、新增(即:时间复杂度为O(n)) + +#### 2. 链表的特性 +- 单向链表: node、 上下元素链接用指针、head/next +- 双向链表: entry +- 新增节点:前继节点的next指针指向新节点,新节点的next指针指向之前的下一个节点 +- 新增节点:前驱节点的next指针打掉,移到后继的节点去 +- 访问慢(即:时间复杂度为O(n)) +- 删除、新增(即:时间复杂度为O(1)) + +#### 3. 跳表的特性 +- 只能用于链表元素有序的情况 +- 跳表是基于链表的 +- 跳表原理:升维思想 + 空间换时间(索引) +- 跳表对标的是平衡树(AVL Tree)和二分查找,是一种插入、删除、搜索都是O(logn)的数据结构 +- 其最大的优势是原理简单、容易实现、方便扩展、效率更高。 + +#### 4. 栈(stack)的特性 +- 先入后出(LIFO:Last in - First out); +- 添加、删除皆为O(1) + +#### 5. 队列(Queue)的特性 +- 先入先出(FIFO:Fist in - First out) +- 添加、删除皆为O(1) + +#### 6. 双端队列(Deque:Double-End Queue)的特性 +- 两端都可以进出的队列 +- 添加、删除皆为O(1) +- 查询时 O(n)--遍历元素 + +#### 7. 优先队列(Priority Queue)的特性 +- 添加、删除皆为O(1) +- 取出操作: O(logN)--按照元素的优先级取出 +- 底层具体实现的数据结构较为多样和复杂:heap(堆)、treap等 diff --git a/Week_01/trapping-rain-water.php b/Week_01/trapping-rain-water.php new file mode 100644 index 00000000..0924edc8 --- /dev/null +++ b/Week_01/trapping-rain-water.php @@ -0,0 +1,81 @@ + $max_val) { + $max_val = $height[$i]; + $max_index = $i; + } + } + + // 左边到最大高度 + $left_height = $height[0]; + $area = 0; + for ($i = 0; $i < $max_index; $i++) { + if ($left_height < $height[$i]) { + $left_height = $height[$i]; + } else { + $area += $left_height - $height[$i]; + } + } + + // 右边到最大高度 + $right_height = $height[count($height)-1]; + for ($i = count($height)-1; $i > $max_index; $i--) { + if ($right_height < $height[$i]) { + $right_height = $height[$i]; + } else { + $area += $right_height - $height[$i]; + } + } + return $area; + + } + + /** + * 【未测试-待优化】 + * 根据栈:比栈顶元素小就入栈,如果下一个元素比栈顶元素大,则该部分就是凹槽,即计算面积 + * @param $height + * @return int|mixed + */ + function trap_stack($height){ +// $stack = new SplStack(); +// $res = 0; +// for($i=0; $iisEmpty() || $height[$i] < $height[$stack->top()]) { +// $stack->push($i); +// } else { +// while (!$stack->isEmpty() && $height[$i] > $height[$stack->top()]) { +// $top = $stack->top(); +// if (!$stack->isEmpty()) { +// $width = $i - $stack->top(); +// $height_new = min($height[$i], $height[$stack->top()]) - $height[$top]; +// $res += $width * $height_new; +// } +// } +// $stack->push($i); +// } +// } +// +// return $res; + + } +} + +$obj = new Solution(); +$arr = [0,1,0,2,1,0,1,3,2,1,2,1]; +$result = $obj->trap_stack($arr); +print_r($result); \ No newline at end of file diff --git a/Week_02/NOTE.md b/Week_02/NOTE.md index 50de3041..64439bcf 100644 --- a/Week_02/NOTE.md +++ b/Week_02/NOTE.md @@ -1 +1,115 @@ -学习笔记 \ No newline at end of file +## 一、哈希 +### 1. 哈希(hash table)的特性 +哈希表又称作散列表,是根据关键码值(key-value)而直接进行访问的数据结构。它通过把关键码值映射到表中的一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数(Hash Function),存放记录的数组叫做哈希表(或散列表) + +### 2. 哈希(hash table)的工程实践 +- 电话号码簿 +- 用户信息表 +- 缓存(LRU Cache) +- 键值对存储(Redis) +- 区块链 + +### 3. 时间复杂度:(一般情况下是O(1)) + + + +## 二、映射(map) - key-value对,key不重复 +### 1. 映射的特性 +- new HashMap()/TreeMap() +- map.set(key, val) +- map.get(key) +- map.has(key) +- map.size() +- map.clear() + + +## 三、集合(set) - 不重复元素的集合 +### 1. 集合的特性 +- new HashSet()/TreeSet() +- set.add(val) +- set.delete(val) +- set.has(val) +PHP接口: +https://www.php.net/manual/en/function.hash.php +https://www.php.net/manual/en/function.hash-update.php + +Python接口 +https://docs.python.org/zh-cn/3/library/stdtypes.html#set-types-set-frozenset +https://docs.python.org/zh-cn/3/library/stdtypes.html#dict +dict、list类型 + + +切题四件套:1.clarification; 2.possible solution --> optimal (space & time); 3.code; 4.test cases +## 一、树 +### 1. 树(tree)的特性 +Linked-List 就是特殊的tree;Tree 就是特殊化的 graph + + +## 二、二叉树 +### 1. 二叉树(tree)的特性 +``` +graph TD + 根节点 --> 左子树 + 左子树 --> 左1子树 + 左子树 --> 左2子树 + 根节点 --> 右子树 + 右子树 --> 右1子树 + 右子树 --> 右2子树 +``` + + +### 2.二叉树遍历 +- 前序遍历【Pre-Order】 +``` +graph LR +根节点-->左子树 +左子树-->右子树 +``` + +- 中序遍历【Pre-Order】 +``` +graph LR +左子树-->根节点 +根节点-->右子树 +``` + +- 后续遍历 +``` +graph LR +左子树-->右子树 +右子树-->根节点 +``` + +- 层次遍历:按照二叉树中的层次从左到右依次遍历每层中的结点。具体的实现思路是:通过使用队列的数据结构,从树的根结点开始,依次将其左孩子和右孩子入队。而后每次队列中一个结点出队,都将其左孩子和右孩子入队,直到树中所有结点都出队,出队结点的先后顺序就是层次遍历的最终结果。 + +## 三、二叉搜索树 +### 1. 二叉搜索树 +二叉搜索树也叫二叉排序树,有序二叉树、排序二叉树,是指一颗空树或者具有下列性质的二叉树: + 左子树上所有节点的值均小于它的根节点的值; + 右子树上所有节点的值均大于它的根节点的值; + 以此类推,左右子树分别为二叉查找树(这就是重要性) + +### 2.二叉搜索树排序:中序遍历 + +### 3.二叉搜索树时间复杂度 +查询、插入、删除 都是O(logn) + +## 一、堆 +### 1. 堆(heap)的特性 +- 可以迅速找到一堆数中的最大值或最小值的数据结构 +- 根节点最大的堆叫做大顶堆或大根堆 +- 根节点最小的堆叫做小顶堆或小根堆 +- 常见的堆:二叉堆、斐波那契堆 + +假设是最大堆,则常见操作(api): +find-max: O(1) +delete-max: O(logN) +insert(create): O(1)或O(logN) + + +## 二、二叉堆 +### 1. 二叉堆的特性 +- 通过完全二叉树实现 +- 二叉堆(大顶)他满足下列性质: +- - 是一颗完全树 +- - 树中任意节点的值总是 >= 其子节点的值 diff --git a/Week_02/binary-tree-inorder.php b/Week_02/binary-tree-inorder.php new file mode 100644 index 00000000..b45f244e --- /dev/null +++ b/Week_02/binary-tree-inorder.php @@ -0,0 +1,83 @@ +inorderTraversal($root->left); + array_push($this->result, $root->val); + $this->inorderTraversal($root->right); + } + return $this->result; + } +} + +class Node{ + public $value; + public $left; + public $right; +} + + +//中序遍历,左子树---> 根节点 ---> 右子树 +function inorder($root) +{ + $stack = array(); + $center_node = $root; + while (!empty($stack) || $center_node != null) { + while ($center_node != null) { + array_push($stack, $center_node); + $center_node = $center_node->left; + } + + $center_node = array_pop($stack); + echo $center_node->value . " "; + + $center_node = $center_node->right; + } +} + +$a=new Node(); +$b=new Node(); +$c=new Node(); +$d=new Node(); +$e=new Node(); +$f=new Node(); +$a->value='A'; +$b->value='B'; +$c->value='C'; +$d->value='D'; +$e->value='E'; +$f->value='F'; +$a->left=$b; +$a->right=$c; +$b->left=$d; +$c->left=$e; +$c->right=$f; +inorder($a);//D B A E C F diff --git a/Week_02/two-sum.php b/Week_02/two-sum.php new file mode 100644 index 00000000..d3e07122 --- /dev/null +++ b/Week_02/two-sum.php @@ -0,0 +1,52 @@ +$val) { + $other = $target - $val; + if ($key != 0 && array_search($other, $numbers)){ + return [$key, array_search($other, $numbers)]; + } + } + +} + +function twoSum3($nums, $target) { + $arr = array(); + foreach($nums as $key=>$value){ + if(array_key_exists($target - $value, $arr)){ + return [$arr[$target - $value],$key]; + } + $arr[$value] = $key; + } +} + +$nums = [2,6,7,9,10]; + + +$result = twoSum([2,6,7,9,10], 9); +$result1 = twoSum2([3,3], 6); +$result2 = twoSum3([2,6,7,9,10], 9); +echo '
';
+//print_r($result);
+print_R($result1);
+//print_R($result2);
\ No newline at end of file
diff --git a/Week_04/NOTE.md b/Week_04/NOTE.md
index 50de3041..59a5de81 100644
--- a/Week_04/NOTE.md
+++ b/Week_04/NOTE.md
@@ -1 +1,80 @@
-学习笔记
\ No newline at end of file
+## 一、二分查找
+### 1. 二分查找的前提 (在有序的里面进行查找)
+- 目标函数单调性(单调递增或单调递减)
+
+- 存在上下界(bounded)
+
+- 能够通过索引下标进行访问(index accessible)
+
+### 2. 二分法思想
+二分法查找针对的是一个有序的数据集合,每次通过与区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为0
+
+二分查找非常高效,假设数据大小是n,每次查找后数据都会缩小为原来的一半,也就是会除以2,最坏情况下,直到查找区间被缩小为空,才停止
+
+当n/2k = 1时,k是总共缩小的次数,而每一次缩小操作只涉及两个数据的大小比较,经过K次区间缩小的操作,时间复杂度就是O(k),n/2k = 1得到k=log2 n,故时间复杂度就是O(logn)
+
+### 3. 二分查找的递归与非递归实现
+#### 最简单的二分查找实现(有序数据集合中不存在重复的数据)
+```
+public static int binarySearch(int[]A,int value) {
+        int low = 0;
+        int len = A.length;
+        int high = len -1;
+​
+        while(low <= high) {
+            int mid = (low + high)>>1;
+            if(A[mid] == value)
+                return mid;
+            else if (A[mid] < value)
+                low = mid +1;
+            else
+                high = mid -1;
+        }
+        return -1;
+    }
+
+二分查找易错的地方:
+
+1. 循环退出的条件
+
+注意是low <= high,而不是low>1)
+
+```
+
+#### 二分法的递归实现
+```
+    /**
+     * 二分法搜索的递归实现
+     */
+    public static int bsearch(int[] a,int n,int val) {
+        return bsearchInternally(a,0,n-1,val);
+    }
+​
+    private static int bsearchInternally(int[] a,int low,int high,int value) {
+        if(low >high) 
+            return -1;
+        int mid = low +((high - low)>> 1);
+        if(a[mid] == value) {
+            return mid;
+        }else if(a[mid] < value) 
+            return bsearchInternally(a,mid+1,high,value);
+        else {
+            return bsearchInternally(a,low,mid-1,value);
+        }
+    }
+
+```
+#### 二分法查找应用场景
+- 二分查找依赖顺序表结构
+     
+- 二分查找不能依赖如链表的的其他结构,主要原因是二分查找算法需要按照下标随机访问元素,链表随机访问的时间复杂度是O(n),使用链表存储,二分查找的时间复杂度就会变得很高
+     
+- 二分查找针对的有序数组
+     
+- 二分查找对数据要求必须是有序的,如果数据没有序,则需要先排序
+     
+- 数据量太小或数据量太大也不适合二分查找
diff --git a/Week_04/fen-fa-bing-gan.php b/Week_04/fen-fa-bing-gan.php
new file mode 100644
index 00000000..e534f4ce
--- /dev/null
+++ b/Week_04/fen-fa-bing-gan.php
@@ -0,0 +1,34 @@
+ $reach) return false;
+            $reach = max($reach, $i + $nums[$i]);
+        }
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/Week_06/NOTE.md b/Week_06/NOTE.md
index 50de3041..74d6656d 100644
--- a/Week_06/NOTE.md
+++ b/Week_06/NOTE.md
@@ -1 +1,13 @@
-学习笔记
\ No newline at end of file
+### 动态规划
+
+#### 递推:递归 + 记忆化
+#### 状态的定义
+#### 状态转义方程:递推公式
+#### 最优子结构
+#### 常见的面试题:斐波那契数列、爬楼梯、乘积最大子序列列等
+#### 阶梯思路:
+- 找出 重复子问题
+- 定义状态数组
+- 推导 DP 方程
+
+### 动态规划也是最难学的,要多练习!
diff --git a/Week_06/minimum-path-sum.php b/Week_06/minimum-path-sum.php
new file mode 100644
index 00000000..08e6eabf
--- /dev/null
+++ b/Week_06/minimum-path-sum.php
@@ -0,0 +1,36 @@
+=0 && s[i] == s[left] {
+            left--
+            count++
+        }
+
+        for left>=0 &&right < size && s[left] == s[right] {
+            left--
+            right++
+            count++
+        }
+    }
+
+    return count
+}