面试题:字符串与数组相关

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;
}

猜你喜欢

转载自blog.csdn.net/wm12345645/article/details/81913122