算法题--字符串排列组合、n皇后、字符出现次数(C++)


目录

 

题目:输入一个字符串,按字典序打印出该字符串中字符的所有排列。

题目:输入一个字符串,求字符的所有组合。

题目:输入一个含有8个数字的数组,把这8个数字放在正方体的8个顶点上,使得正方体上相对的面上的4个顶点的和都相等。

题目:N皇后问题。

题目:在一个字符串中找到第一个只出现一次的字符,并返回它的位置。

题目:定义一个函数,输入两个字符串,从第一个字符串中删除在第二个字符串中出现的所有字符。

题目:定义一个函数,删除字符串中所有重复出现的字符。

题目:定义函数,判断两个字符是否互为变位词。

题目:字符流中第一个只出现一次的字符。


题目:输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba.

看下图,用回溯法,直观明了。

图片来自牛客网剑指offer中一位网友的回答。

/*
这是一个字符串排列问题,考虑使用回溯法
可以分为两部分来做
第一部分:求所有可能在第一个位置的字符,即把第一个字符与后面所有字符交换,包括自己和自己交换
第二部分:固定第一个字符,求后面所有字符的排列,即又回到第一部分
其中注意一个问题:如果第一个字符与后面某一个位置字符相同,则不用交换
*/

class Solution {
public:
    vector<string> Permutation(string str) {
        vector<string> all;
        if(str.size() == 0){
            return all;
        }
        string tmp;
        recur(str, tmp, all, 0);
        return all;
    }
    void recur(string str, string& tmp, vector<string> &all, int start){
        if(start < 0 || str.size() == 0){
            return;
        }
        if(str.size() == start){
            all.push_back(tmp);
            return;
        }
        for(int i = start; i < str.size(); i++){
            if(i != start && str[i] == str[start]){    //如果字符相同,不用交换
                continue;
            }
            swap(str[i], str[start]);
            tmp += str[start];
            recur(str, tmp, all, start + 1);
            tmp.pop_back();            //回溯法的关键
        }
    }
};

题目:输入一个字符串,求字符的所有组合。例如:输入abc,则它们的组合有a、b、c、ab、ac、bc、abc。其中ab和ba只是一种组合。

/*
输入n个字符,那么形成的组合长度有1、2、... 、n
在n个字符中求长m的字符时,可以分成两部分:第一个字符和其余所有字符
如果组合中包含第一个字符,则在剩余字符中求m-1个字符
如果组合中不包含第一个字符,则在剩余字符中求m个字符
就可以用递归的方法求解
*/
class Solution
{
public:
    vector<string> combination(string str){
        vector<string> all;
	if (str.size() == 0) {
		return all;
	}
	string tmp;
	for (int i = 1; i <= str.size(); i++) {
		recur(str, tmp, 0, i, all);
	}
	return all;
    }
	
    void recur(string str, string &tmp, int start, int number, vector<string>& all){
        if (number == 0) {
	    all.push_back(tmp);
	    return;
	}
	if (start == str.size()) {
	    return;
	}
	if (number > str.size() - start) {
	    return;
	}
	tmp += str[start];
	recur(str, tmp, start + 1, number - 1, all);
	tmp.pop_back();
	recur(str, tmp, start + 1, number, all);
    }
};

题目:输入一个含有8个数字的数组,判断有没有可能把这8个数字分别放在正方体的8个顶点上,使得正方体上三组相对的面上的4个顶点的和都相等。

/*
简而言之,这就是一个全排列问题
把这8个数全排列,之后判断正方体的三个像对面是否相等即可
*/
class Solutin{
public:
    bool cubeVertex(vector<int> vec) {
	if (vec.size() != 8) {
		return false;
	}
	return cubeCore(vec, 0);
    }
    bool cubeCore(vector<int>& vec, int start) {
	if (vec.size() != 8 || start < 0) {
		return false;
	}
	bool result = false;
	if (start == vec.size() - 1) { //判断正方体的三个相对面是否相等
	    if (Sum(vec, 0, 1, 2, 3) == Sum(vec, 4, 5, 6, 7)
		&& Sum(vec, 0, 2, 4, 6) == Sum(vec, 1, 3, 5, 7)
		&& Sum(vec, 0, 1, 4, 5) == Sum(vec, 2, 3, 6, 7)) {
	        result = true;
	    }
	}
	else {
	    for (int i = start; i < vec.size(); i++) {
                if (i != start && vec[i] == vec[start]) {
		    continue;
		}
		swap(vec[i], vec[start]);
		result = cubeCore(vec, start + 1);
		if (result) {  //一旦为true,则直接break,后面无需在做排序
		    break;
		}
		swap(vec[i], vec[start]);
	    }
	}
	return result;
    }
    int Sum(vector<int> vec, int i, int j, int k, int l) {
	return vec[i] + vec[j] + vec[k] + vec[l];
    }
}

题目:N皇后问题,在一个N*N的棋盘上放置N个皇后,使其不能互相攻击(同一行、同一列、同一斜线上的皇后都会自动攻击),即任意两个皇后不得处于同一行、同一列、同意斜线上。

/*
经典的N皇后问题
假如N=4
我们可以定义一个数组column[4],数组中第i个数字表示位于第i行的皇后的列号
并将0,1,2,3分别放入数组中,放入的时候判断是否在同一列以及是否时一条斜线
它们肯定不会在同一行,因为数组下标0,1,2,3各不相同,因此所在行肯定不同
*/
class Solution{
public:
    int totalNQueens(int n) {
	if (n < 0) {
	    return 0;
	}
	vector<int> vec(n);
	int sum = 0;
	QueenCore(0, n, vec, sum);
	return sum;
    }
    void QueenCore(int index, int n, vector<int> &vec, int &sum) {
	if (index >= n) {
	    sum++;
	}
	else {
	    for (int i = 0; i < n; i++) {
	        vec[index] = i;
		if (Diagonal(vec, index)) { //判断是否在同一列或者是否在一条斜线上
		    QueenCore(index + 1, n, vec, sum);
		}
	    }
	}
    }
    bool Diagonal(const vector<int> &vec, int index) {
	for (int i = 0; i < index; i++) {
	    if ((abs(vec[i] - vec[index]) == abs(i - index)) || vec[i] == vec[index]) {             
	        return false;
	    }
	}
	return true;
    }
}

题目:在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写)

/*
char是一次长度为8的数据类型。因此有256中可能。
创建一个大小为256的数组,下标对应ASCII码值,存储的数是出现的次数
*/
int FirstNotRepeatingChar(string str) {
    if(str.size() < 0 || str.size() > 10000) {
        return -1;
    }
    int* position = new int[256];
    for(int i = 0; i < 256; i++){
        position[i] = 0;
    }
    for(int i = 0; i < str.size(); i++){
        position[str[i]]++;
    }
    for(int i = 0; i < str.size(); i++){
        if(position[str[i]] == 1){
            return i;
        }
    }
    return -1;
}

题目:定义一个函数,输入两个字符串,从第一个字符串中删除在第二个字符串中出现的所有字符。

void deleteSubstring(string& str1, const string& str2){
	if(str1.size() == 0 || str2.size() == 0){
		return;
	}
	bool* map = new bool[256];
	for(int i = 0; i < 256; i++){
		map[i] = false;
	}
	for(int i = 0; i < str2.size(); i++){
		map[str2[i]] = true;
	}
	for(int it = str1.begin(); it != str1.end(); it++){
		if(map[*it] == true){
			str1.erase(it);
		}
	}
}

题目:定义一个函数,删除字符串中所有重复出现的字符。

void deleteDupstring(string& str){
	if(str.size() == 0){
		return;
	}
	bool* map = new bool[256];
	for(int i = 0; i < 256; i++){
		map[i] = false;
	}
	for(int it = str.begin(); it != str.end(); it++){
		if(map[*it] == true){
			str.erase(it);
		}
		else{
			map[*it] = true;
		}
	}
}

题目:在英语中,如果两个单词出现的字母相同,并且每个字母出现的次数也相同,那么两个单词护卫变位词。定义函数,是否互为变位词。

bool isAnagram(const string& str1, const string& str2){
	if(str1.size() == 0 || str2.size() == 0 || str1.size() != str2.size()){
		return false;
	}
	int* map = new int[256];
	for(int i = 0; i < 256; i++){
		map[i] = 0;
	}
	for(int i = 0; i < str1.size(); i++){
		map[str[i]]++;
	}
	for(int i = 0; i < str2.size(); i++){
		map[str[i]]--;
	}
	for(int i = 0; i < 256; i++){
		if(map[str[i]] != 0){
			return false;
		}
	}
	return true;
}

题目:字符流中第一个只出现一次的字符。

// 把字符流的字符一次保存下来
class Solution{
private:
	string str;
	int count[256];

public:
	Solution() {
		for(int i = 0; i < 256; i++){
			count[i] = 0;
		}
	}

	void insert(char ch){
		str += to_string(ch);
		count[ch]++;
	}

	char firstOnce(){
		int len = str.size();
		for(int i = 0; i < len; i++){
			if(count[str[i]] == 1){
				return str[i];
			}
		}
		return '#';
	}
};


// 不保存字符
class Solution1{
private:
	int index;
	int count[256];

public:
	Solution1() : index(0) {
		for(int i = 0; i < 256; i++){
			count[i] = -1;
		}
	}

	void inset(char ch){
		if(count[ch] == -1){
			count[ch] = index;
		}
		else if(count[ch] >= 0){
			count[ch] = -2;
		}
		index++;
	}

	char firstOnce(){
		char tmp = '\0';
		int minIndex = INT_MAX;
		for(int i = 0; i < 256; i++){
			if(count[i] >= 0 && count[i] < minIndex){
				minIndex = count[i];
				tmp = char(i);
			}
		}
		return tmp;
	}
};

参考

剑指offer

猜你喜欢

转载自blog.csdn.net/weixin_39953502/article/details/81297827