程序员面试金典(一)C++版

文章目录

          • 1.确定字符互异
          • 2.原串翻转
          • 3.确定两串乱序同构
          • 4.空格替换
          • 5.基本字符串压缩
          • 6.像素翻转
          • 7.清除行列
          • 8.翻转子串
          • 9.链表中倒数第k个结点

1.确定字符互异

  请实现一个算法,确定一个字符串的所有字符是否全都不同。这里我们要求不允许使用额外的存储结构…给定一个string iniString,请返回一个bool值,True代表所有字符全都不同,False代表存在相同的字符。保证字符串中的字符为ASCII字符。字符串的长度小于等于3000

测试样例:
“aeiou”
返回:True
“BarackObama”
返回:False

class Different {
public:
	bool checkDifferent(string iniString) {
		// write code here
		if (iniString.size() < 0)
		{
			return false;
		}

		for (int i = 0; i < iniString.size(); i++)
		{
			for (int j = i + 1; j < iniString.size(); j++)
			{
				if (iniString[i] == iniString[j])
					return false;
			}
		}
		return true;
	}
};
  • 确定字符互异
2.原串翻转

  请实现一个算法,在不使用额外数据结构和储存空间的情况下,翻转一个给定的字符串(可以使用单个过程变量)。给定一个string iniString,请返回一个string,为翻转后的字符串。保证字符串的长度小于等于5000

测试样例:
“This is nowcoder”
返回:“redocwon si sihT”

class Reverse {
public:
    string reverseString(string iniString) {
        // write code here
        if(iniString.size() <= 0 || iniString.size() > 5000)
        {
            return 0;
        }
        
        int head = 0;
        int tail = iniString.size() - 1;
        while(head < tail)
        {
            char tmp = iniString[head];
            iniString[head] = iniString[tail];
            iniString[tail] = tmp;
            head++;
            tail--;
        }
        return iniString;
    }
};
  • 原串翻转
3.确定两串乱序同构

  给定两个字符串,请编写程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。这里规定大小写为不同字符,且考虑字符串中的空格。给定一个string stringA和一个string stringB,请返回一个bool,代表两串是否重新排列后可相同。保证两串的长度都小于等于5000

测试样例:
“This is nowcoder”,“is This nowcoder”
返回:true
“Here you are”,“Are you here”
返回:false

class Same {
public:
    bool checkSam(string stringA, string stringB) {
        // write code here
        //考虑到字符重组所以利用哈希表统计字符出现次数
        if (stringA.size() != stringB.size() || stringA.size() == 0 || stringB.size() == 0)
			return false;

		char A[256] = { 0 };
		char B[256] = { 0 };

		for (int i = 0; i < stringA.size(); i++)
		{
			A[stringA[i]]++;
			B[stringB[i]]++;
		}

		for (int i = 0; i < 256; i++)
		{
			if (A[i] != B[i])
				return false;
		}

		return true;
    }
};
  • 确定两串乱序同构
4.空格替换

  请编写一个方法,将字符串中的空格全部替换为“%20”。假定该字符串有足够的空间存放新增的字符,并且知道字符串的真实长度(小于等于1000),同时保证字符串由大小写的英文字母组成。给定一个string iniString 为原始的串,以及串的长度 int len, 返回替换后的string

"Mr John Smith”,13
返回:“Mr%20John%20Smith”
”Hello World”,12
返回:”Hello%20%20World”

class Replacement {
public:
    string replaceSpace(string iniString, int length) {
        // write code here
        if (length == 0)
			return nullptr;

		int spacenumber = 0;
		for (int i = 0; i < length; i++)
		{
			if (iniString[i] == ' ')
				spacenumber++;
		}
		int change_length = length + spacenumber * 2;
        iniString.resize(change_length);
        
		int tail1 = length - 1;
		int tail2 = change_length - 1;
		while (tail1 != tail2)
		{
			if (iniString[tail1] == ' ')
			{
				iniString[tail2--] = '0';
				iniString[tail2--] = '2';
				iniString[tail2--] = '%';
 			}
			else
			{
				iniString[tail2--] = iniString[tail1];
			}

			tail1--;
		}
        return iniString;
	}
};
5.基本字符串压缩

  利用字符重复出现的次数,编写一个方法,实现基本的字符串压缩功能。比如,字符串“aabcccccaaa”经压缩会变成“a2b1c5a3”。若压缩后的字符串没有变短,则返回原先的字符串,给定一个string iniString为待压缩的串(长度小于等于10000),保证串内字符均由大小写英文字母组成,返回一个string,为所求的压缩后或未变化的串

测试样例
“aabcccccaaa”
返回:“a2b1c5a3”
“welcometonowcoderrrrr”
返回:“welcometonowcoderrrrr”

class Zipper {
public:
	string zipString(string iniString) {
		// write code here
		string newstr;

		int cou = 1;
		for (int i = 1; i < iniString.size(); i++)
		{
			if (iniString[i - 1] == iniString[i])
			{
				cou++;
				if (i == iniString.size() - 1)
				{
					string stmp;
					stringstream ss;
					ss << cou;
					ss >> stmp;
					cou = 1;
					newstr += iniString[i - 1] + stmp;
				}
				continue;
			}
			string stmp;
			stringstream ss;
			ss << cou;
			ss >> stmp;
			cou = 1;
			newstr += iniString[i - 1] + stmp;
		
		}
		if (iniString.size() <= newstr.size())
			return iniString;
		else
			return newstr;
	}
};
  • 基本字符串压缩
6.像素翻转

  有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度。给定一个NxN的矩阵,和矩阵的阶数N,请返回旋转后的NxN矩阵,保证N小于等于500,图像元素小于等于256

[[1,2,3],[4,5,6],[7,8,9]],3
返回:[[7,4,1],[8,5,2],[9,6,3]]

class Transform {
public:
	vector<vector<int> > transformImage(vector<vector<int> > mat, int n)
	{
		// write code here
		//从最外层向内层执行
		for (int lay = 0; lay < n / 2; lay++)//确定循环层数
		{
			int initial = lay;//初始边界
			int end = n - 1 - lay;//结束边界

			for (int i = initial; i < end; i++)
			{
				int offset = i - initial;//计算偏移量
				int top = mat[initial][i];//取上元素

				//左到上
				mat[initial][i] = mat[end - offset][initial];
				//下到左
				mat[end - offset][initial] = mat[end][end - offset];
				//右到下
				mat[end][end - offset] = mat[i][end];
				//上到右
				mat[i][end] = top;
			}
		}

		return mat;
	}
};
  • 像素翻转
7.清除行列

  请编写一个算法,若N阶方阵中某个元素为0,则将其所在的行与列清零。给定一个N阶方阵int[][](C++中为vector>)mat和矩阵的阶数n,请返回完成操作后的int[][]方阵(C++中为vector>),保证n小于等于300,矩阵中的元素为int范围内

[[1,2,3],[0,1,2],[0,0,1]]
返回:[[0,0,3],[0,0,0],[0,0,0]]

class Clearer {
public:
	bool IsNotExist(const vector<int>& a, int d)
	{
		for (int i = 0; i < a.size(); i++)
		{
			if (a[i] == d)
				return false;
		}

		return true;
	}

	vector<vector<int> > clearZero(vector<vector<int> > mat, int n) {
		// write code here
		vector<int> rows, cols;//包含0的行列

		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				if (mat[i][j] == 0)
				{
					if(IsNotExist(rows, i))
						rows.push_back(i);

					if (IsNotExist(cols, j))
						cols.push_back(j);
				}
			}
		}

		for (int i = 0; i < rows.size(); i++)
		{
			for (int j = 0; j < n; j++)
			{
				mat[rows[i]][j] = 0;
			}
		}


		for (int i = 0; i < cols.size(); i++)
		{
			for (int j = 0; j < n; j++)
			{
				mat[j][cols[i]] = 0;
			}
		}

		return mat;
	}
};
  • 清除行列
8.翻转子串

  假定我们都知道非常高效的算法来检查一个单词是否为其他字符串的子串。请将这个算法编写成一个函数,给定两个字符串s1和s2,请编写代码检查s2是否为s1旋转而成,要求只能调用一次检查子串的函数。给定两个字符串s1,s2,请返回bool值代表s2是否由s1旋转而成。字符串中字符为英文字母和空格,区分大小写,字符串长度小于等于1000

“Hello world”,"worldhello "
返回:false
“waterbottle”,“erbottlewat”
返回:true

class ReverseEqual {
public:
	bool checkReverseEqual(string s1, string s2) {
		// write code here
		char s1word[256] = {0};
		char s2word[256] = {0};

		if (s1.size() != s2.size())
		{
			return false;
		}

		for (int i = 0; i < s1.size(); i++)
		{
			s1word[s1[i]]++;
			s2word[s2[i]]++;
		}
		
		for (int i = 0; i < 256; i++)
		{
			if (s1word[i] != s2word[i])
				return false;
		}

		return true;
	}
};
  • 翻转字串
9.链表中倒数第k个结点

  输入一个链表,输出该链表中倒数第k个结点

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        ListNode* fast = pListHead;
        ListNode* slow = pListHead; 
        
        if(pListHead == nullptr)
            return nullptr;
        //快慢指针法
        unsigned int steps = 1;
        for(;fast != nullptr;steps++)
        {
            if(steps >k)
                slow = slow->next;
            fast = fast->next;
        }
        
        return steps > k? slow:nullptr;
    }
};
  • 链表中倒数第k个结点

你可能感兴趣的:(数据结构与算法)