1,空格替换
题目解析:将字符串中的空格 ‘ ’ 替换为 ‘ %20 ’。
解题思路:使用string类中的resize函数进行扩容。然后从后往前遍历,进行空格替换。
class Replacement {
public:
string replaceSpace(string iniString, int length) {
if(length<=0)
return iniString;
int blank = 0; //计算空格的数量
for(int i=0;i<length;++i)
if(iniString[i]==' ')
++blank;
int newLength = length+(blank<<1); //对字符串进行扩容
iniString.resize(newLength);
int index1 = length-1;
int index2 = newLength-1;
while(index1>=0 && index2>index1){ //从后遍历,将空格替换掉
if(iniString[index1]==' '){
iniString[index2--]='0';
iniString[index2--]='2';
iniString[index2--]='%';
}
else
iniString[index2--]=iniString[index1];
--index1;
}
return iniString;
}
};
2,左旋转字符串
题目解析:将字符串 abcXY123 左旋转3位变为 XY123abc
解题思路 :string.substr( int n , int len ),这个函数是将字符串string从第 n 为开始到 n 的后 len 位 切分出来 。
abcXYZ123 (3,3) =XYZ , 有了这个函数,只需要将被旋转的字符串后面再加一个自己,然后使用
substr函数, abcXY123abcXY123 (3 ,len)=XY123abc(len是字符串长度),旋转完成
class Solution {
public:
string LeftRotateString(string str, int n) {
int len = str.length();
if(len == 0) return "";
n = n % len; //n可能大于字符串长度
str += str; //给自己加上自己
return str.substr(n, len);
}
};
3,数组中的逆序对
题目描述:
有一组数,对于其中任意两个数组,若前面一个大于后面一个数字,则这两个数字组成一个逆序对。请设计一个高效的算法,计算给定数组中的逆序对个数。
给定一个int数组A和它的大小n,请返回A中的逆序对个数。保证n小于等于5000。
测试样例:
[1,2,3,4,5,6,7,0],8
题目分析:
就是找像(1,0)(2,0)(3,0)(4,0)这样的逆序对的个数
解题思路:用两层循环的方法时间复杂度为O(n^2)。
用归并排序的思想,将数组划分为子数组,在子数组进行归并时,统计逆序对的个数 ,并完成排序。
那么如何在排序两个有序数组的时候,统计逆序对的个数?
下面是代码
//寻找逆对数对
#include<vector>
class AntiOrder {
public:
int count(vector<int> A, int n) {
if (0 == n)return 0;
vector<int> v(A); //这是用来保存有序数组的空间,在递归函数中使用传引用的方式
int ret = _count(A, v, 0, n - 1);
return ret;
}
int _count(vector<int>& A, vector<int>& v, int left, int right)
{
if (left == right)
return 0;
int mid = (left + right) >> 1;
int leftcount = _count(A, v, left, mid);
int rightcount = _count(A, v, mid + 1, right);
int i = mid;
int j = right;
int pos = right;
int count = 0;
while (i >= left && j > mid)
{
if (A[i] > A[j]) //左数组的值比右数组的值大
{
count += j - mid; //逆序对的个数增加右数组的剩余个数,因为是有序的
v[pos--] = A[i--];//指针--,并保存到有序空间
}
else //右数组的值更大
{
v[pos--] = A[j--]; //不用增加逆序对的个数
}
}
for (; i >= left; i--) //右数组先排完了
{
v[pos--] = A[i];
}
for (; j > mid; j--) //左数组先排完了
{
v[pos--] = A[j];
}
for (int i = left; i <= right; i++) //将排好的有序的数组,拷贝到源数组中
{
A[i] = v[i];
}
return count + leftcount + rightcount;//最后将本次统计的逆序对个数和左右两数组的
逆序对个数加起来
}
};
4,顺时针打印数组
注意:当只有一行或者只有一列时,必须进行判断,要不然就会打印两次
//顺序打印数组
#include<vector>
class Printer {
public:
vector<int> clockwisePrint(vector<vector<int> > mat, int n, int m) {
vector<int> result;
int left = 0;
int right = m-1;
int top = 0;
int btm = n-1;
while (left <= right && top <= btm)
{
//打印上边
for (int i = left; i <= right ; i++)
{
result.push_back(mat[top][i]);
}
//打印左边
for (int i = top + 1; i <= btm; i++)
{
result.push_back(mat[i][right]);
}
//打印下边
if (top<btm)//必须是大于两行,才需要打印下边,如果是一行,就交给上边打印
{
for (int i = right - 1; i >= left; i--)
{
result.push_back(mat[btm][i]);
}
}
//打印右边
if (left < right)//必须是大于两列,才能打印到左
{
for (int i = btm - 1; i >top; i--)
{
result.push_back(mat[i][left]);
}
}
top++;
btm--;
left++;
right--;
}
return result;
}
};
5,求连续的子数组的和
例如:输入的数组为{1,-2,3,10,-4,7,2,-5},和最大的子数组为{3,10,-4,7,2},输出连续子数组的最大和是8。
#include<iostream>
using namespace std;
int mian()
{
int n, curSum = 0, maxSum = -1e5;
cin >> n;
int arr[n];
for (int i = 0; i<n; i++)
{
cin >> arr[i];
curSum += arr[i]; //先将当前连续数组的和记录下来
if (maxSum<curSum) //如果最大连续数组的和大于当前连续数组的和,那么就交换,这样最大连续数组和保存下来
{
maxSum = curSum;
}
if (curSum<0)//如果当前连续数组的和是负数,那么就直接丢弃它,因为留着只能给找到一个更大的连续数组帮倒忙,因为是负数,加上会更小
curSum = 0;
}
cout << maxSum << endl;
return 0;
}