输出第二个字符串在第一个字符串中的连接次序

题目:输入两个字符串,比如 abdbcc (source string) 和 abc (target string),输出第二个字符串在第一个字符串中的连接次序。即输出125、126、145、146.

方法一:递归方法,总结理解书(面试宝典)上的代码

      重要的点:需要声明一个和目标字符串长度相同的 index 数组 (printArray[]) 用于存放满足条件的连接次序,然后递归比较,满足条件时打印或者存放结果于指定数组中。

      分析:对于这两个字符串,第一个字符 a 在位置 0 都相等,所以问题递归转化为在字符串 bdbcc 中找 bc 的连接顺序,然后进一步转化为在 dbcc 中找 c 的连接顺序,依次递归 ...... 。

002706_C2AG_3349205.png003722_bS1j_3349205.png

如上图,第一轮两个字符串都是从位置 0 开始比较,发现 TargetStr[0] = SourceStr[0],  TargetStr[1] = SourceStr[1], 然后继续在 SourceStr 中找和 TargetStr[2] 相同的元素,发现有两个位置满足。

然后对于字符 Target[1],继续从上次满足条件的下一位置往后继续查找满足的位置,若找到,继续重复查找 Target[2] 在 SourceStr 中的位置,如此依次向前递归。最终结果如下图

005228_JD93_3349205.png

代码如下:

/**************************** author: Charleey@2017/07/02 ***************************

*    iTargetStr:        目标字符串

*    iSourceStr:    源字符串

*    ipPrintArray:    满足条件的 index 数组,长度和 iTargetStr 相同

*    iPrintArrayLen:标识对于 ipPrintArray 已经填充到第几位

*    tStartPos:        目标字符串的起始比较位置

*    sStartPos:        源字符串的起始比较位置

*    ioResultIndex:    存储最满足条件的 index 集合

**********************************************************************************/

void PrintfArray(const string& iTargetStr, const string& iSourceStr, int *ipPrintArray, int iPrintArrayLen, int tStartPos, int sStartPos, vector<vector<int>>& ioResultIndex)

{

    if (iPrintArrayLen == iTargetStr.length())    //若打印的数组中已经填充到最后一位,说明一轮查找已经结束

    {

        vector<int> lOneResultIndex;

        for (int i = 0; i < iPrintArrayLen; ++i)

            lOneResultIndex.push_back(*(ipPrintArray + i));

        ioResultIndex.push_back(lOneResultIndex);

        return;

    }

    for (int i = sStartPos; i < iSourceStr.length(); ++i)    //外层循环确保对于每一个 target string 中的字符都能比较到最后一个位置

    {

        for (int j = tStartPos; j < iTargetStr.length(); ++j)

        {

            if (iSourceStr[i] == iTargetStr[j])    //对于 target string 中的一个字符,若找到在 source string 中的位置,                                                

            {                                    //二者都从下一个位置 (i+1, j+1) 开始继续重复上述比较

                ipPrintArray[iPrintArrayLen] = i + 1;

                PrintfArray(iTargetStr, iSourceStr, ipPrintArray, iPrintArrayLen + 1, j + 1, i + 1, ioResultIndex);

            }

        }

    }

}

方法二:思想仍然来源于书(面试宝典)。

       分析:首先得计算出第二个字符串各个字符在第一个字符串中出现的位置,利用其位置构造多叉树(构造规则是子节点的 index 必须大于父节点的 index),然后遍历多叉树即完成相应的组合。

011438_DDD9_3349205.png

因为思路比较直观,直接贴出代码,如下:

/**************************** author: Charleey@2017/07/02 ***************************

*    iTargetStr:        目标字符串

*    iSourceStr:    源字符串

*    lResultVec:    存储目标字符串中的每一字符在源字符串中的位置

**********************************************************************************/

void FindEachCharPosition(const string& iTargetStr, const string& iSourceStr, vector<vector<int>>& lResultVec)

{

    if (iSourceStr.size() >= iTargetStr.size())

    {

        vector<vector<int>> lTempVec;

        for (size_t i = 0; i < iTargetStr.size(); ++i)

        {

            vector<int> lEachCharactor;

            for (size_t j = 0; j < iSourceStr.size(); ++j)

            {

                if (iTargetStr[i] == iSourceStr[j])

                    lEachCharactor.push_back(j + 1);

            }

            lTempVec.push_back(lEachCharactor);

        }

        if (lTempVec.size() == iTargetStr.size())

            for (auto lEachIndexVec : lTempVec)

                lResultVec.push_back(lEachIndexVec);

    }

}

/**************************** author: Charleey@2017/07/02 ***************************

*    iIndex:          标识上述图中多叉树的第几层

*    iData:          目标字符串中的每一字符在源字符串中的位置

*    iResult:      每一轮遍历的结果

*    ioResultIndex:存储最满足条件的 index 集合

**********************************************************************************/

void RecursivelyPrint(int iIndex, vector<vector<int>>& iData, vector<int>& iResult, vector<vector<int>>& ioResultIndex)

{

    if (iIndex == iData.size())    //一种组合遍历结束

    {

        ioResultIndex.push_back(iResult);

        return;

    }

    for (auto it : iData[iIndex])

    {

        if (0 == iIndex)    //多叉树的第一层,直接存储

        {

            iResult.push_back(it);

            RecursivelyPrint(iIndex + 1, iData, iResult, ioResultIndex);

            iResult.pop_back();

        }

        else

        {

            if (it > iResult[iIndex - 1])    //若不是第一层,需要判断子节点的 index 是否大于父节点的 index, 只有大于的时候才能存储

            {                                //因为该位置被上一层中的字符占用的话,当前层的字符不能使用

                iResult.push_back(it);

                RecursivelyPrint(iIndex + 1, iData, iResult, ioResultIndex);

                iResult.pop_back();            //每次一轮结束后,该位置的 index 要 pop 出去,然后新一轮写入的 index 才有意义

            }

        }

    }

}

 

 

转载于:https://my.oschina.net/u/3349205/blog/1113876

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 首先,需要定义一个链表结构体,每个结点存储一个字符和指向下一个结点的指针。 然后,从键盘读入一个字符串,逐个字符创建链表结点,并将其插入链表的头部。 最后,遍历链表,按相反的次序输出每个结点存储的字符到显示屏。 具体实现可以参考以下代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> // 链表结构体 typedef struct node { char data; // 存储的字符 struct node* next; // 指向下一个结点的指针 } Node; int main() { char str[100]; // 存储输入的字符串 Node* head = NULL; // 链表头指针 // 从键盘读入一个字符串 printf("请输入一个字符串:"); scanf("%s", str); // 逐个字符创建链表结点,并将其插入链表头部 int len = strlen(str); for (int i = 0; i < len; i++) { Node* node = (Node*)malloc(sizeof(Node)); node->data = str[i]; node->next = head; head = node; } // 遍历链表,按相反的次序输出每个结点存储的字符到显示屏 printf("相反的次序输出字符串:"); Node* p = head; while (p != NULL) { printf("%c", p->data); p = p->next; } printf("\n"); // 释放链表结点的内存 p = head; while (p != NULL) { Node* q = p; p = p->next; free(q); } return 0; } ``` ### 回答2: 首先,在C语言可以使用结构体来实现链表。结构体可以包含一个字符型变量和一个指针变量,指向下一个结点。定义一个结构体Node如下: ``` typedef struct Node{ char c; struct Node *next; }Node; ``` 现在,我们可以开始实现将字符串存入链表的程序了。算法思路可以如下: 1. 读入字符串。 2. 新建一个头结点,将第一个字符存入头结点。 3. 循环读入字符串的每个字符,新建一个结点,将字符存入结点。将新结点插入到链表。 4. 最终得到一个包含所有字符的链表。 代码如下: ``` int main(){ char str[100]; printf("请输入字符串:"); scanf("%s",str); Node *head = (Node*)malloc(sizeof(Node)); head -> c = str[0]; head -> next = NULL; int len = strlen(str); for(int i=1; i<len; i++){ Node *p = (Node*)malloc(sizeof(Node)); p -> c = str[i]; p -> next = head; head = p; } // 遍历链表并输出 Node *p = head; while(p){ printf("%c",p->c); p = p->next; } return 0; } ``` 在程序,我们从第二个字符开始循环读入,建立新结点并将新结点插入到链表的头部。最后得到的head就是整个链表的头结点。遍历链表并输出时,按照相反的次序输出即可。 ### 回答3: 题目要求将键盘输入的字符串存储到链表,然后按相反的顺序输出到显示屏上。这个问题可以通过以下步骤解决: 步骤一:定义链表结构体 首先要定义一个链表结构体来存储字符串,每个结点存储1个字符。链表结构体可以定义如下: struct ListNode{ char data; ListNode* next; }; 步骤二:读取输入的字符串并存储到链表 程序可以通过循环方式读取键盘输入的字符,并将每一个字符存储到链表,可以使用以下代码实现: ListNode* head = NULL; //链表头结点指针 ListNode* p = NULL; //链表指针 char c; //读取的字符 while((c = getchar()) != '\n'){ ListNode* node = new ListNode; node->data = c; node->next = NULL; if(head == NULL){ //如果是第一个元素,则将其作为头结点 head = node; p = head; } else{ //将结点加入链表末尾 p->next = node; p = p->next; } } 步骤三:按相反的顺序输出链表 输出链表时,可以使用递归的方式来遍历整个链表。具体来说,递归函数可以按逆序输出链表,然后输出当前结点。如下所示: void reversePrint(ListNode* p){ if(p != NULL){ reversePrint(p->next); putchar(p->data); } } 步骤四:完整代码 以下是完整的代码: #include<iostream> using namespace std; struct ListNode{ char data; ListNode* next; }; void reversePrint(ListNode* p){ if(p!=NULL){ reversePrint(p->next); putchar(p->data); } } int main(){ ListNode* head = NULL; ListNode* p = NULL; char c; while((c=getchar())!='\n'){ ListNode* node = new ListNode; node->data = c; node->next = NULL; if(head == NULL){ head = node; p = head; } else{ p->next = node; p = p->next; } } reversePrint(head); return 0; } 上述代码可以读取任意长度的字符串并逆序输出到屏幕上。注意在使用链表时一定要记得释放内存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值