学算法题过程

1 数组

1.1 二分查找

704
注意判断循环的条件是left < right
vector类型有.size()函数,表示数组长度
可以用右移来除以2

1.2 移除元素

27

双指针法:

一个下标遍历,遇见不符合的跳过

另一个下标按顺序记录符合的

相向:左边找不符合,右边找符合放到左边不符合的位置

1.3 有序数组的平方

977

双指针,从两端往中间,选出大的放到新vector

1.4 长度最小的子数组

209

双指针→滑动窗口

O(n)

右指针遍历扩大,当满足条件时,使用循环递增左指针直到该次长度最小

1.5 螺旋矩阵

59

二维数组容器初始化:vector> matrix(n, vector(n, 0));

可以只用i和j表示当前位置,不需要很多变量;记得使用i--

如果是奇数,最后中间的单独赋值

2 链表

结构体构造函数:初始化更方便

struct node{
    int data;
    string str;
    char x;
    //注意构造函数最后这里没有分号哦!
  node() :x(), str(), data(){} //无参数的构造函数数组初始化时调用
  node(int a, string b, char c) :data(a), str(b), x(c){}//有参构造
};

2.1 移除链表元素

203

可以设置一个虚拟头结点,这样原头结点不需要特殊处理了

有关条件判断的问题

正确写法:n != NULL && n->next != NULL

错误写法:n->next != NULL && n != NULL

2.2 设计链表

707

建立链表的时候就设置虚拟头结点

NULL实质是0

nullptr是一个特殊的空指针值,表示空指针更安全

delete指针后要将指针指向nullptr

2.3 翻转链表

206

用多个指针记录翻转所需的结点

2.4 两两交换链表中的节点

24

设虚拟头结点

注意交换后,链接下一个的有向边也要更新

2.5 删除链表的倒数第N个节点

19

关键是找到倒数第N个节点

设双指针,一个先向后N个,然后两个指针同时向后直到链表末尾

2.6 相交链表

160 && 面试题02.07

尾部对齐,从短的开始遍历即可

2.7 环形链表

142

非常巧妙

双指针,fast每次走2,slow每次走1

delta=1所以如果有环则必在环内相交

slow再走等量距离必仍然在交点,且与相交后重走slow有一段重合。刚重合的地方就是刚入环的地方。即在交点与在起点同时走slow,刚重合的地方就是入环的地方。

if break与循环条件可以等价

3 Hash表/哈希表/散列表

set/multiset/unordered_set

map/multimap/unordered_map

3.1 有效的字母异位词

242

数组要初始化为0:a[26] = {0}

3.2 两个数组的交集

349

明确容器:set且是unordered_set(不可重复)

容器的迭代器:

v.begin()

v.end()

v.find(): 返回对应迭代器或者v.end()

v.insert ()

容器初始化:

unordered_set numSet1(nums1.begin(), nums1.end());

3.3 快乐数

202

3.4 两数之和

1

Markdown可以和HTML的语法兼容,可以通过HTML的上标和下标标签来实现效果:

标签 写法 效果
上标 210 210
下标 H2O H2O

暴力的时间复杂度:O(n2)

联想,使用unordered_map将查询的复杂度从O(n)降到O(1)

从而将整体时间复杂度降到O(n)

vector result(2, 0)可以直接用{0, 0}

左值类型自动匹配右值类型:auto iter = map.find()

iter->second

3.5 四数相加II

454

分成两个 二数之和

将二数之和的结果放到unordered_map

键为和,值为该和出现的次数

结果为 所有((两个 二数之和 的和为0的次数) 的乘积 )的和

3.6 赎金信

383

疑惑的问题:容器之间比较运算?

要有使用--的意识

3.7 三数之和

15

双指针法

遍历a,左指针向右调整,右指针向左调整,确定b和c

a需要去重

bc也要去重

3.8 四数之和

18

思路同三数之和

注意:

  1. while(l < r && nums[l] == nums[l+1])

    一定要先判断l

  2. if((long)nums[i] + nums[j] + nums[l] + nums[r] < target)

    不加long会溢出

  3. int r = nums.size() - 1;

    注意要不要忘记减一

  4. if(nums[i] + nums[j] > target && nums[i] + nums[j] >= 0)

    剪枝的时候不要漏了nums[i] + nums[j] >= 0

4 字符串

4.1 反转字符串

344

交换变量a、b可以通过位运算:

a = a ^ b;
b = a ^ b;
a = a ^ b;

4.2 反转字符串II

541

每间隔k就反转

注意:

​ C语言,函数要修改变量的值需要用指针

​ C++中只需要在声明参数的时候使用引用就行

4.3 路径加密

lcr122

least cost route

双指针:

​ 确定新串的大小

​ 从尾部遍历

​ 每遍历到替换的地方,旧指针减1,新指针替换并减去对应大小

4.4 反转字符串中的单词

151

使用双指针去空格

采用两次反转:全字符串反转和单词反转

注意:

​ leetcode越界报错:ERROR: AddressSanitizer: stack-buffer-overflow on address

​ 不能用!='\0'判断循环出口,要用

4.5 动态口令

lcr182

为了让本题更有意义,提升一下本题难度:不能申请额外空间,只能在本串上操作

具体步骤为:

  1. 反转整个字符串
  2. 反转区间为后n的子串
  3. 反转区间为前1-n的子串

4.6 实现 strStr()

28

你可能感兴趣的:(c++)