# 0416【LeetCode 算法笔记】Task01 LeetCode入门 + 数据结构基础

41 阅读4分钟

参考资料:

开源内容:github.com/datawhalech…

电子网站:datawhalechina.github.io/leetcode-no…

image.png

——————————

程序 = 数据结构 + 算法

classDiagram
数据结构 --|> 逻辑结构
数据结构 --|> 物理结构
逻辑结构 --|> 集合
逻辑结构 --|> 线性
逻辑结构 --|> 树形
逻辑结构 --|> 图形
物理结构 --|> 顺序存储
物理结构 --|> 链式存储
数据结构: 数据以何种方式进行组织、存储
class 逻辑结构{
数据元素之间的相互关系
}
class 集合{
数据无序且唯一
}
class 线性{
数组、链表、栈、队列、哈希表
}
class 树形{
二叉树、多叉树、字典树
}
class 图形{
无向图、有向图、连通图
}
class 物理结构{
数据的逻辑结构 在计算机中的存储方式
}
class 顺序存储{ 
+占用最少的存储空间 
-需要占用一片地址连续的存储单元,并且存储分配需要事先进行
-移动、删除等操作较慢
}
class 链式存储{
+ 存储空间不必事先分配,可临时申请。不会造成空间的浪费
+ 插入、移动、删除等操作效率比顺序存储高
- 需要额外的存储后继指针的空间。
}

算法的基本特性: 输入、输出、有穷性、确定性、可行性。

算法追求的目标:所需运行时间更小,占用内存空间更小。

  • 正确、可读、健壮

image.png

——————

算法复杂度: 在问题的输入规模为 n 的条件下, 程序的时间使用情况 和 空间使用情况。

image.png

时间复杂度 T(n)

1、不包含循环、递归语句。 O(1)

2、线性 O(n) 单层循环

3、平方 O(n2)O(n^2) 双层循环 且 每层循环次数为 n

4、阶乘 O(n!) 全排列、旅行商问题暴力解法

5、对数 O(log n) 二分查找、分治

6、线性对数 O(n log n) 快速排序、归并排序、堆排序

image.png

时间复杂度的最佳、最坏、平均

image.png

空间复杂度 S(n)

来源 1: 算法范围内定义的变量 占用的存储空间。

来源 2: 递归栈帧空间

image.png

image.png

————————

目标: 通过解决 LeetCode 题库中的问题来练习编程技能,提升算法能力。

Leetbook、计划等

推荐刷题顺序和目录如下:

1. 初级算法2. 数组类算法3. 数组和字符串4. 链表类算法5. 哈希表6. 队列 & 栈7. 递归8. 二分查找9. 二叉树10. 中级算法11. 高级算法12. 算法面试题汇总

image.png

flowchart LR
看到题思考五分钟 -->|有思路| 写代码
看到题思考五分钟 -->|无思路| 看题解
看题解 -->|有思路| 根据题解思路实现代码
看题解 -->|无思路| 认真阅读题解的代码.并理解代码的逻辑

🚩—— Day1

2235. 两整数相加

😂 这题也值得出嘛

class Solution: # O(1) O(1)
    def sum(self, num1: int, num2: int) -> int:
        return num1 + num2
class Solution {// O(1) O(1)
public:
    int sum(int num1, int num2) {
        return num1 + num2;        
    }
};

1929. 数组串联

⭐ 数组串联的时间复杂度为 O(n)

image.png

class Solution: # O(n) O(1)
    def getConcatenation(self, nums: List[int]) -> List[int]:
        return nums * 2
class Solution: # O(n) O(1)
    def getConcatenation(self, nums: List[int]) -> List[int]:
        return nums + nums
class Solution: # O(n) O(1)
    def getConcatenation(self, nums: List[int]) -> List[int]:
        nums.extend(nums)
        return nums
class Solution {// O(n) O(1)
public:
    vector<int> getConcatenation(vector<int>& nums) {
        int n = nums.size();
        for (int i = 0; i < n; ++i){// 这里要注意 提前计算 n。因为后续 nums 的长度变大
            nums.emplace_back(nums[i]);
        }
        return nums;
    }
};

771. 宝石与石头

优化: 哈希化 后, 空间换时间, 可将时间复杂度 从 O(mn) 降到 O(m + n)

⭐ 哈希化 可将查找时间复杂度降至 线性 O(n)

class Solution:  # O(m + n)  O(m)  m 为 jewels 的长度
    def numJewelsInStones(self, jewels: str, stones: str) -> int:
        jewelsSet = set(jewels)
        ret = 0
        for c in stones:
            if c in jewelsSet: # 哈希表为 O(1)  字符串为 O(n)
                ret += 1

        return ret 
class Solution {// 哈希化 空间换时间 O(m + n) O(m) m 为 jewels 的长度
public:
    int numJewelsInStones(string jewels, string stones) {
        unordered_set<char> jewelsSet(jewels.begin(), jewels.end());
        int ret = 0;
        for (char c : stones){
            if (jewelsSet.contains(c)){
                ++ret;
            }
        }
        return ret;
    }
};

🚩—— Day2

1480. 一维数组的动态和

⭐ 原地叠加修改成前缀和数组

# 需要问清楚 是否允许修改原来的数组。不然创建一个新数组存储值即可
class Solution: # O(n) O(1)
    def runningSum(self, nums: List[int]) -> List[int]:
        for i in range(1, len(nums)):
            nums[i] += nums[i - 1]

        return nums
class Solution {// O(n) O(1)
public:
    vector<int> runningSum(vector<int>& nums) {
        for (int i = 1; i < nums.size(); ++i){
            nums[i] += nums[i - 1];
        }
        return nums;
    }
};

709. 转换成小写字母

class Solution:
    def toLowerCase(self, s: str) -> str:
        return s.lower()
class Solution {// API  O(n) O(1)
public:
    string toLowerCase(string s) {
        for (char & ch : s){
            ch = tolower(ch);
        }
        return s;
    }
};

⭐ 大写字母 ord() + 32 (按位或替代)后得到 小写字母

class Solution: # O(n)  O(1)
    def toLowerCase(self, s: str) -> str:
        # 大写字母 [65, 90]  + 32 后变成  小写
        # 小写字母 [97, 122]
        lis = list(s)
        for i, c in enumerate(lis):
            if 65 <= ord(c) <= 90:  # 注意范围, 非字母部分 无需转换
                lis[i] = chr(ord(c) | 32) # 按位或 后,恰好实现了 加 32 操作

        return ''.join(lis)
        #print(ord('A'), ord('Z'))
        #print(ord('a'), ord('z'))
class Solution {// O(n) O(1)
public:
    string toLowerCase(string s) {
        for (char & ch : s){
            if ( 65 <= ch && ch <= 90){// C++  可以直接比较
                ch |= 32;
            }
        }
        return s;
    }
};

1672. 最富有客户的资产总量

class Solution: # O(mn) O(1)  
    def maximumWealth(self, accounts: List[List[int]]) -> int:
        ret = 0
        for acc in accounts:
            ret = max(ret, sum(acc))

        return ret
class Solution {// O(mn) O(1)
public:
    int maximumWealth(vector<vector<int>>& accounts) {
        int ret = 0;
        for (auto & acc : accounts){
            ret = max(ret, accumulate(acc.begin(), acc.end(), 0));
        }
        return ret;
    }
};