朋友分享给我的,简单记录下
题目描述
请实现一个简单的代码缩进功能,把一段未缩进的代码,通过多次操作,最终实现每一行的缩进长度要求。
一次操作是指:
一次操作时缩进一个TAB长度
一次操作可以选择一行或者连续多行同时缩进。
给出的要缩进的代码长度用一个数组表示,要求计算出最少需要操作多少次。
输入描述:
一个整数n。表示代码总行数,取值范围【1,65535】
接下来一行有n个整数,依次表示第1~n行的最终缩进长度要求,取值范围:[0,1000000]。
示例1:
输入:
5
1 2 3 2 1
输出:
3
说明:最少需要操作三次,第1次操作全选所有行,缩进1个TAB;第二次操作选择2,3,4行,再缩进1个TAB;第三次才做选择第3行,再缩进1个TAB。
示例2:
输入:
9
0 1 2 0 2 4 2 1 0
输出:
6
说明:
第一次缩进后:0 0 1 0 2 4 2 1 0
第二次缩进后:0 0 0 0 2 4 2 1 0
第三次缩进后:0 0 0 0 1 3 1 0 0
第四次缩进后:0 0 0 0 0 2 0 0 0
第五次缩进后:0 0 0 0 0 1 0 0 0
第六次缩进后:0 0 0 0 0 0 0 0 0
解题思路
我们最终的目标是将一个连续数组的所有值通过操作都变成0,我们需要记录达到这个目标所用的最小的操作次数。
那么如何操作用的次数最少呢?我们采用以下策略:
- 对于连续的子数组,就对这里连续的数组所有的成员都执行一次缩进操作(即数值-1)。
- 对于不连续的数组,也就是单个的一个数据(以a[i]为例),就只能对a[i]执行a[i]次缩进,将它变成0。
根据以上思路,我们的代码思路就是:
1.寻找给出的数组的第一连续子数组:然后对这个这个子数组缩进x次(x表示这个连续数组中的所有成员的最小值),并记录操作的次数。
2.重复上述操作,知道找不到任何一个连续子数组(也就表示着数组中所有成员的值都为0)。此时返回最小操作次数即可。
伪代码
int calMinTab(vector<int> tabVec, int nums) {
int start = 0, end = 0;
while (true) {
//寻找第一个连续子数组,并记录begin和end,以及连续数组的最小值(minTab)
if (findFirstContinusVec(tabVec, begin, end, minTab)) {
//记录对此连续数组的操作次数
rst = rst + minTab;
//对所有数组中的值都减去操作的次数(模仿真正缩进操作)
doTab(tabVec, beign, end);
//如果找不到任何数组,说明数组为0了,退出循环。
} else break;
}
return rst;
}
完整代码
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
vector<int> tabVec;
int callMinTab() {
if (tabVec.size() == 0) return 0;
while (true) {
//找到数组中第一个连续的数组
if (findFirstContinusVec(tabVec)) {
//找到了数组中第一个连续的数组
//rst加上该连续数组中的最小值,
rst += minNums;
//对这个连续数组中的每个元素减去该最小值
doTab(tabVec);
}
else return rst;
}
return rst;
}
void doTab(vector<int> &tabVec) {
for (int i = begin; i <= end; i++) {
tabVec[i] = tabVec[i] - minNums;
}
}
//找到数组中第一个连续的数组,并且找到这个连续数组中的最小值minNums,开始位置begin,结束位置begin
bool findFirstContinusVec(vector<int> tabVec) {
//是否找到连续数组的第一个非零值
bool ifFisrtNumsFind = false;
int i = 0;
for(;i< tabVec.size();i++) {
//当找到连续数组的第一个非零值时
if (ifFisrtNumsFind == true) {
if (tabVec[i] == 0) {
//找到连续数组的最后一个非零值
end = i - 1;
return true;
} else {
//更新最小值
if (tabVec[i] < minNums) minNums = tabVec[i];
}
}
//当没有找到连续数组的第一个非零值时
else if (ifFisrtNumsFind == false && tabVec[i] != 0) {
//找到连续数组的第一个非零值
minNums = tabVec[i];
begin = i;
ifFisrtNumsFind = true;
}
}
if (ifFisrtNumsFind && i == tabVec.size()) {
end = i -1;
return true;
}
//没有找到任何连续数组,那么返回False
return false;
}
private:
int rst = 0;
int minNums = INT_MAX;
int begin = 0;
int end = 0;
};
int main()
{
int num, n;
Solution t;
while (cin >> num)
{
while (num--)
{
cin >> n;
t.tabVec.push_back(n);
}
return t.callMinTab();
}
}
结尾
本系列的所有题目都是面试实习群里的群友们面试完反馈的,想要加群一起交流分享新鲜的互联网面试经验的同学,请关注我的微信公众号:"奔跑的鲁班七号”,回复:“面试学习交流群” 获得群二维码,入群学习分享即可。