方法:(以下两步翻转可以互换)
- 主对角线翻转
- 竖中轴翻转
最开始的想法是循环,每次循环或向右,或向下,或向左,或向上。
之后发现,一轮顺时针遍历是由向右,向下,向左,向上四个操作组成,不应该分割。如此循环若干次(对矩阵进行若干次顺时针遍历)值,直到遍历完整个矩阵。
方法:设定边界+模拟 。用四个变量表示当前矩阵的边界,然后将元素一个一个地填入。
需要注意的是:在到达每一条边的边界时需要及时更新边界。
方法:
- 正则表达式(我不会,需要学习)
- 有限状态机(官方题解)
- 讨论所有可能的情况,这是我第一次用的方法。
这里补充一下第三种解法。有效数字有这么几种可能:
- 整数
- 小数
- 整数e/E整数
- 小数e/E整数
方法:大数加法 + copy_backward()
方法:使用行数组和列数组分别指示行和列是否有元素为0。 空间复杂度O(m + n)。
计算重叠面积,然后用总面积减去重叠面积。
要画图,考虑各种可能的情况。
矩形的放置有两种情况:
- 矩形交叠。如果两个矩形交叠,
- 矩形不交叠。
两个矩形的水平边投影到
x
轴上的线段分别为[ax1,ax2]
和[bx1,bx2]
。竖直边投影到y
轴的线段有[ay1,ay2]
和by1,by2]
。如果两个矩形交叠,重叠部分的水平投影是
[max(ax1,bx2),min(ax2,bx2)]
,竖直部分的水平投影是[max(ay1,by2),min(ay2,by2)]
.根据重叠部分的线段可计算重叠部分的面积。只有重叠线段都大于
0
,重叠面积才会大于0
,否则就为0
。
题目给定的数字有正有负,为了保证数字转字符串的正确性,要先把数字转为正数,最后再根据数字是否大于
0
决定是否加-
。这时候要特别小心边界条件:极小值的相反数超过了int
的表示范围,因此要做相应的检查判断。
下面两道题目都用到了 摩尔投票算法 。
摩尔投票算法可以这么理解:
假设现在有 n n n个投票人, k k k个候选人。初始时 k k k个候选人的位置都是空。在投票的过程中,每一个投票人走上投票台,按照如下规则进行投票:
- 如果他在候选人中看到和自己同名的人,那么就把票投给他;
- 如果看到有候选人的票数是零,就把候选人请下台,然后自己走到候选人的位置,并给自己投一票
- 如果既没看到和自己名字相同的人,也没看到候选人的票数是零,就拿走所有候选人的一张选票。
重复上述过程,直到所有人都上过一次投票台。
思路和算法:
复制原数组,用复制的数组状态改变原数组的状态
引入多余的状态在原地修改。具体而言;
- 细胞状态原来是活的,但现在死亡,用状态
-1
标识- 细胞状态原来是死的,但现在活了,用状态
2
标识最后再遍历一遍数组,把状态
-1
和2
改为0
和1
。
算法和思路
-
题目要求求解文件的最长绝对路径,有两个需要注意的地方:
- 是文件,而不是文件夹
- 最长的绝对路径
-
观察题目,不难发现每当出现字符
\n
时,就进入了新一级目录,\n
后面\t
的个数表示目录的级数。 -
假设文件处于第 n n n级,要求得文件的最长的绝对路径,必须保存该文件前 n − 1 n - 1 n−1目录(包括第
0
级根目录)。 -
注意到遍历完第一个
1
级目录的下面所有子目录后,才能遍历第二个1
级目录
通过以上分析,可以提出如下算法:
vector<string>
保存当前所遍历到的文件/文件夹的前面所有级的文件目录- 遇到
\n
,根据\t
的个数判断当前文件/文件夹所在的目录级数 - 遇到其他字母,一直读取,直到遇到
\n
结束。若当前字符串中存在.
,说明它是一个文件,计算该文件的绝对路径,并更新结果;否则它是一个文件夹,将文件夹加入到vector<string>
的第 n n n个位置。 - 重复2-3,直到结束遍历。
小贴士
\n
和\t
都是一个字符,而非两个。
方法:大数加法
具体而言,把字符串表示的数字按照从低位到高位的顺序依次存入vector
中,然后用两个vector
模拟加法运算,并把结果存放到结果vector
中,最后把结果vector
转为字符串。
一道困难又无聊的模拟题。
这是一道简单的模拟题。
首先写出0-9
的英文表示:zero one two three four five six seven eight nine
观察以上英文单词,不难发现如下规律:
z
唯一确定zero
w
唯一确定two
u
唯一确定four
x
唯一确定six
g
唯一确定eight
zero
,one
,two
,four
共有o
,确定zero
,two
,four
,即可确定one
zero
,four
,three
共有r
, 确定了four
和zero
即可确定three
four
和five
共有f
,确定了four
即可确定five
vsix
和seven
共有s
, 确定了six
即可确定seven
five
,six
,eight
,nine
共有i
,确定了five
,six
,eight
即可确定nine
按照上述规律,提出了如下的算法:
- 统计字符串中字符的频次
- 按照上述规律根据字符频次确定数字个数
题目类型:数位统计。数位统计问题一般都是按位统计。
1. 思路和算法
在本题中,按位查找数字前缀。因此,需要定义一个函数int f(int prefix, int n)
,该函数的作用返回[1,n]
中数字前缀是prefix
的数字个数cnt
。
cnt < k
,要找的数字的前缀大于prefix
,因此递增prefix
(因为 k ≤ n k \leq n k≤n,所以不需要考虑prefix
递增的溢出问题),并更新k
为k - cnt
。cnt >= k
,说明目标数字的前缀是prefix
,需要进一步确定前缀的下一个数字,因此从 p r e f i x × 10 prefix \times 10 prefix×10开始查找,同时-- k
。(为什么?prefix
也不仅是一个前缀,还是一个数字。以prefix
为前缀的数字中就包含prefix
本身。因为下一步查找的是 p r e f i x × 10 prefix \times 10 prefix×10,而以 p r e f i x × 10 prefix \times 10 prefix×10为前缀的数字不包含prefix
,因此搜索范围k
也要相应地缩小)。- 重复上述操作,直到
k = 1
2. 函数int f(int prefix, int n)
设前缀prefix
是x
位,n
是y
位,以prefix
为前缀的数字num
可以是
x
x
x位,
x
+
1
x + 1
x+1位,
⋯
\cdots
⋯,
y
y
y位。
设num
的位数是z
,
- 当
x
≤
z
<
y
x \leq z < y
x≤z<y,共有
1
0
z
−
x
10^{z - x}
10z−x个数字的前缀是
prefix
- 当
z
=
y
z = y
z=y
- 若数字
n
的前x
位大于prefix
,共有 1 0 y − z 10 ^ {y - z} 10y−z个数字前缀是prefix
- 若数字
n
的前x
位大于prefix
,共有 n − p r e f i x × 1 0 y − z + 1 n - prefix \times 10 ^ {y - z} + 1 n−prefix×10y−z+1个数字前缀是prefix
- 若数字
n
的前x
位小于于prefix
,共有 0 0 0个数字前缀是prefix
- 若数字
453.最小操作次数使数组元素相等
个人认为这道题目还是很锻炼问题的抽象能力的。
任选$ n - 1 $个元素加 1 1 1,等价于任选 1 1 1个元素减 1 1 1。因为因为我们关心的不是最终的相等元素是什么,而是元素之间的相对值。