• 剑指Offer :字符串的排列


    题目 1

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

    示例

    输入:

    abc
    

    输出:

    abc
    acb
    bac
    bca
    cba
    cab
    

    解题思路

    可以把一个字符串看成由两部分组成:第一部分是它的第一个字符;第二部分是后面的所有字符。求整个字符串的排列,可以看成两步。
    1.求所有可能出现在第一个位置的字符。
    2.固定第一个字符,求后面所有字符的排列。这时仍把后面所有字符分成两部分:后面字符的第一个字符,以及这个字符之后的所有字符。

    代码实现

    #include <stdio.h>
    
    void Permutation(char* string, char* strBegin);
    
    void Permutation(char* string)
    {
        if (string == NULL) {
            return;
        }
        
        Permutation(string, string);
    }
    
    void swap(char* strA, char* strB)
    {
        char temp = *strA;
        *strA = *strB;
        *strB = temp;
    }
    
    void Permutation(char* string, char* strBegin)
    {
        if (*strBegin == '') {
            printf("%s
    ", string);
        } else {
            for (char* strCh = strBegin; *strCh != ''; ++strCh) {
                // 有重复字符时,跳过
                if ((*strCh == *strBegin) && (strCh != strBegin)) {
                    continue;
                }
    
                swap(strCh, strBegin);
                Permutation(string, strBegin + 1);
                swap(strCh, strBegin);
            }
        }
    }
    
    int main(void)
    {
        char string[] = "abc";
        Permutation(string);
    
        return 0;
    }
    

    题目 2

    如果不是求字符的所有排列,而是求字符的所有组合,应该怎么办呢?还是输入三个字符 a、b、c,则它们的组合有 a、b、c、ab、ac、bc、abc。当交换字符串中的两个字符时,虽然能得到两个不同的排列,但却是同一个组合。比如 ab 和 ba 是不同的排列,但只算一个组合。

    示例

    输入:

    abc
    

    输出:

    a
    b
    c
    ab
    ac
    bc
    abc
    

    解题思路

    可以把这 n 个字符分成两部分:第一个字符和其余的所有字符。如果组合里包含第一个字符,则下一步在剩余的字符里选取 m-1个字 符:如果组合里不包含第一个字符,则下一步在剩余的 n-1 个字符里选取 m 个字符。也就是说,我们可以把求 n 个字符组成长度为 m 的组合的问题分解成两个子问题。
    1.求 n-1 个字符串中长度为 m-1 的组合。
    2.求 n-1 个字符的长度为 m 的组合。

    代码实现

    #include <cstdio>
    #include <cstring>
    #include <vector>
    
    void Combination(char* string, int number, std::vector<char>& result);
    
    void Combination(char* string)
    {
        if (string == nullptr) {
            return;
        }
    
        std::vector<char> result;
    
        for (int i = 1; i <= strlen(string); ++i) {
            Combination(string, i, result);
        }
    }
    
    void Combination(char* string, int number, std::vector<char>& result)
    {
        if (number == 0) {
            std::vector<char>::iterator iter = result.begin();
            for (; iter < result.end(); ++iter) {
                printf("%c", *iter);
            }
            printf("
    ");
    
            return;
        }
        
        if (*string == '') {
            return;
        }
    
        result.push_back(*string);
        Combination(string + 1, number - 1, result);
        result.pop_back();
        Combination(string + 1, number, result);
    }
    
    int main(void)
    {
        char string[] = "abc";
        Combination(string);
    
        return 0;
    }
    

    题目 3

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

    解题思路

    相当于先得到a1、a2、a3、a4、a5、a6、a7和a8这 8 个数字的排列,然后判断有没有某一个排列符合题目给定的条件,即 a1+a2+a3+a4 == a5+a6+a7+a8,a1+a3+a5+a7 == a2+a4+a6+a8,并且a1+a2+a5+a6 == a3+a4+a7+a8。

    代码实现

    #include <stdio.h>
    #include <stdbool.h>
    
    void swap(int* a, int*b)
    {
        int temp = *a;
        *a = *b;
        *b = temp;
    }
    
    bool CubVertex(int* A, int length, int begin)
    {
        if ((A == NULL) || (length != 8)) {
            return false;
        }
    
        bool result = false;
        int i = 0;
        
        if (begin == length - 1) {
            if ((A[0] + A[1] + A[2] + A[3] ==A[4] + A[5] + A[6] + A[7]) &&
                (A[0] + A[2] + A[4] + A[6] == A[1] + A[3] + A[5] + A[7]) &&
                (A[0] + A[1] + A[4] + A[5] == A[2] + A[3] + A[6] + A[7])) {
    
                for (i = 0; i < length; ++i) {
                    printf("%d ", A[i]);
                }
                printf("
    ");
                result = true;
            }
        } else {
            for (i = begin; i < length; ++i) {
                swap(&A[begin], &A[i]);
                result = CubVertex(A, length, begin + 1);
                if (result) {
                    break;
                }
    
                swap(&A[begin], &A[i]);
            }
        }
    
        return result;
    }
    
    int main(void)
    {
        int A[8] = {1, 2, 3, 1, 2, 3, 2, 2};
        int B[8] = {1, 2, 3, 1, 8, 3, 2, 2};
    
        if (CubVertex(A, 8, 0)) {
            printf("Yes!
    ");
        } else {
            printf("No!
    ");
        }
    
        if (CubVertex(B, 8, 0)) {
            printf("Yes!
    ");
        } else {
            printf("No!
    ");
        }
        
        return 0;
    }
    /* 运行结果
     * 1 2 3 2 3 2 1 2 
     * Yes!
     * No!
     */
    

    个人博客:

    www.codeapes.cn

  • 相关阅读:
    node.js 入门笔记3
    Linux常用命令大全(非常全!!!)
    数据库导入导出命令(结构+数据)?
    列举 创建索引但是无法命中索引的8种情况。
    简述触发器、函数、视图、存储过程?
    什么是事务?MySQL如何支持事务?
    简述数据库三大范式
    MySQL常见数据库引擎及比较?
    列举常见的关系型数据库和非关系型都有那些?
    操作系统常见面试题
  • 原文地址:https://www.cnblogs.com/codeapes666/p/13196803.html
Copyright © 2020-2023  润新知