【剑指offer】第五十七题(和为 s 的两个数字) 和 第五十八题(翻转字符串)

原创 2018年04月16日 16:29:09

第五十七题:和为 s 的两个数字

题目:

输入一个递增的排序数组和一个数字 s ,在数组中查找两个数,使得它们的和正好是 s 。如果有多对数字的和等于 s ,则输出任意一对即可。

解题程序:

#include<iostream>
#include<stdio.h>
#include<vector>
using namespace std;

// 算法思想:
//          1.设置两个指针,第一个指针指向排序数组的首元素,第二个指针指向数组元素的最后一个元素的位置
//          2.求两个指针所指元素的和,如果两个元素的和大于输入的数字,则尾指针向前移动一位;如果和小于输入数字,
//              则指向首元素的指针向后移动一位;如果和刚好等于输入的数字,那么这两个指针所指元素就是要查找的 数字

bool FindNumbersWithSum(int data[],int len,int sum,int *num1,int *num2)
{
    bool found = false;
    
    if( data == NULL|| len<1 || num1 == NULL || num2 == NULL )
        return found;
    int ahead = len - 1;
    int behind = 0;
    
    while(behind < ahead)
    {
       long long CurSum = data[ahead]  + data[behind];
        
        if(CurSum == sum)
        {
            *num1 = data[behind];
            *num2 = data[ahead];
            found = true;
            break;
        }
        else if(CurSum > sum)
            ahead--;
        else
            behind++;

    }

    return found;
}

// 测试用例

void test()
{
    int data[100] = {0};
    int i = 0;
    int value;
    printf("输入排序数组,以 -1 结束:\n");
    scanf("%d",&value);

    while(value != -1)
    {
        data[i++] = value;
        scanf("%d",&value);
    }
    int len = i; 

    int sum = 0;
    printf("输入要查找的数字的和:\n");
    scanf("%d",&sum);

    int num1;
    int num2;
    bool ret = FindNumbersWithSum(data,len,sum,&num1,&num2);
    if(ret)
        printf("%d = %d + %d\n",sum,num1,num2);
    else
        printf("在排序数组中没有找到两个数的和为 %d\n",sum);
}

int main(void)
{
    test();
    return 0;
}


测试用例:


题目二:和为 s 的连续正数序列

输入一个正数 s ,打印出所有和 为 s 的连续正数序列(至少含有两个数)。例如,输入 15,由于 1+2+3+4+5 = 4+5+6 = 15。所以打印出 3 个连续序列 1 ~ 5、4 ~ 6 和 7 ~ 8。


解题程序:

#include<iostream>
#include<stdio.h>
using namespace std;

// 算法思想:
//          1.设置连个变量,small = 1,big = 2;
//          2.如果从 small 到 big 的序列数字之和大于 s ,则可以去掉序列中较小的值;如果序列之和小于 s,则增大 big,知道增到到
//              small  到 (1+s)/2 为止;如果序列之和等于 s ,则打印出各个和为 s 的序列

// 打印和为 s 的序列

void PrintContinuosSequence(int small,int big)
{
    for(int i=small;i<=big;i++)
    {
        printf("%d\t",i);
    }
    
    printf("\n");
}


void FindContinuousSequence(int sum)
{
    // 判断边界条件
   if(sum<3) 
        return;
   
    int small = 1;
    int big = 2;
    int end = (1+sum) / 2;
    int CurSum = small + big;
   
    // 要保证序列中的最小值小于 (1+s)/2 的值
    while(small < end)
    {
        if(CurSum == sum) 
            PrintContinuosSequence(small,big);

        // 如果序列之和不等于 s,并且当前序列之和大于 s
        while(CurSum > sum && small < end)
        {
            // 去掉最小的数值
            CurSum -= small;
            small++;

            if( CurSum == sum )
                PrintContinuosSequence(small,big);
        }
        
        // 如果序列之和小于 s
        // 序列继续向后移动
        big++;
        CurSum += big;
    }

}


// 测试用例:

void test()
{
    int s;
    printf("请输入序列的和:\n");
    scanf("%d",&s);
   
    // 获取和 s 的子序列
    FindContinuousSequence(s);
}

int main(void)
{
    test();
    return 0;
}

测试用例:



第五十八题:翻转字符串

题目:翻转单词顺序

   输入一个英文句子,翻转句子中单词的顺序,但单词内的字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串 “I am a student.”,则输出 “stundet. a am I ”。


解题程序:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

// 算法思想:
//          1、先给 整个字符串逆序
//          2、然后给每个单词包括标点符号逆序,即可得到结果


void  Reverse(char *pBegin,char* pEnd)
{
   if(pBegin == NULL || pEnd == NULL) 
        return;
   
    // 字符串逆序
    while(pBegin < pEnd)
    {
       char temp = *pBegin; 
        *pBegin = *pEnd;
        *pEnd = temp;
    
        pBegin++;
        pEnd--;
    }
}

char *ReverseSentence(char *pData)
{
    printf("pData = %s\n",pData);
   if(pData == NULL) 
        return NULL;

    // 指向字符串的首元素
    char *pBegin = pData;
    // 指向字符串的尾部元素
    char *pEnd = pData;
    
    while(*pEnd != '\0')
        pEnd++;

    pEnd--;


    // 先翻转整个句子,即逆序整个句子
    Reverse(pBegin,pEnd);

    // 翻转句子中的每个单词以及标点符号

    pBegin = pEnd = pData;

    // 循环遍历字符串中的单词,并翻转
    while(*pBegin != '\0')
    {
        // 如果是空格的话,指向单词首元素的 指针和尾指针都向后移动一个字符,跳过空格
       if(*pBegin == ' ') 
        {
           pBegin++;
            pEnd++;
        }
        // 如果尾指针指向空格或者指向 '\0',则逆序单词
        else if(*pEnd == ' ' || *pEnd == '\0')
        {
           Reverse(pBegin,--pEnd); 

            // 尾指针向后移动一个字符,继续遍历
            pEnd++;
            // 头指针指向下一个单词的第一个字符
            pBegin = pEnd;
        }
        else
            pEnd++;

    }
    printf("pData = %s\n",pData);
    return pData;
}

// 测试用例

void test()
{
    char str[] = "I am a student.";
    char *pStr = NULL; 
    pStr = ReverseSentence(str);
    if( pStr != NULL )
        printf("逆序后的结果为:%s\n",pStr);
    else
       printf("程序出错!\n"); 

    char *str1 = NULL;
    pStr = ReverseSentence(str1);
    if( pStr != NULL )
        printf("逆序后的结果为:%s\n",pStr);
    else
        printf("程序出错!\n"); 
    
    char str2[] = "beautiful";
    pStr = ReverseSentence(str2);
    if( pStr != NULL )
        printf("逆序后的结果为:%s\n",pStr);
    else
       printf("程序出错!\n");     
}

int main(void)
{
    test();
    return 0;
}

测试用例:



题目二:左旋转字符串

字符串的左旋操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋操作的功能。比如,输入字符串 “abcdefg”和 数字 2,该函数将返回左旋转两位得到的结果,"cdefgab"。

解题程序:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

// 算法思想:
//          1.先把字符串的前 n 个字符翻转
//          2、然后把剩下的字符翻转
//          3、最后把整个字符串翻转

void Reverse(char *pBegin,char *pEnd)
{
    if(pBegin == NULL || pEnd == NULL)
        return;
    
    while(pBegin < pEnd)
    {
        char temp = *pBegin;        
        *pBegin = *pEnd;
        *pEnd = temp;

        pBegin++;
        pEnd--;
    }
}

char *LeftRotateString(char *pStr,int n)
{
   if(pStr != NULL) 
    {
        int nLength = strlen(pStr);
        if(nLength >0 && n>0 && n<nLength)
        {
            char *pFirstStart = pStr;
            char *pFirstEnd = pStr + n - 1;
            char *pSecondStart = pStr + n;
            char *pSecondEnd = pStr + nLength - 1;
            
            // 翻转字符串的前面 n 个字符
            Reverse(pFirstStart,pFirstEnd);
            
            // 翻转字符串的后面部分
            Reverse(pSecondStart,pSecondEnd);

            // 翻转整个字符串
            Reverse(pFirstStart,pSecondEnd);

        }
    }
    
    return pStr;
}

// 测试用例

void test()
{
    char str1[] = "abcdefg";
    int len = strlen(str1);
    char *pstr = NULL;

    pstr = LeftRotateString(str1,0);
    if( pstr == NULL )
        printf("error\n");
    else
        printf("字符串%s 从第 %d 个字符翻转后的结果为: %s\n",str1,0,pstr);

    // 左旋 1 个字符
    
    char str2[] = "abcdefg";
    pstr = LeftRotateString(str2,1);
    if( pstr == NULL )
        printf("error\n");
    else
        printf("字符串%s 从第 %d 个字符翻转后的结果为: %s\n",str2,1,pstr);

    // 左旋 2 个字符
    char str3[] = "abcdefg";
    pstr = LeftRotateString(str3,2);
    if( pstr == NULL )
        printf("error\n");
    else
        printf("字符串%s 从第 %d 个字符翻转后的结果为: %s\n",str3,2,pstr);

    // 左旋 len-1 个字符
    char str4[] = "abcdefg";
    pstr = LeftRotateString(str4,len-1);
    if( pstr == NULL )
        printf("error\n");
    else
        printf("字符串%s 从第 %d 个字符翻转后的结果为: %s\n",str4,len-1,pstr);
   
    // 左旋 len 个字符
    char str5[] = "abcdefg";
    pstr = LeftRotateString(str5,len);
    if( pstr == NULL )
        printf("error\n");
    else
        printf("字符串%s 从第 %d 个字符翻转后的结果为: %s\n",str5,len,pstr);
    
    // 左旋 len+1 个字符
    char str6[] = "abcdefg";
    pstr = LeftRotateString(str6,len+1);
    if( pstr == NULL )
        printf("error\n");
    else
        printf("字符串%s 从第 %d 个字符翻转后的结果为: %s\n",str6,len+1,pstr);

    // 字符串为 NULL
    pstr = LeftRotateString(NULL,0);
    if( pstr == NULL )
        printf("error\n");
    else
        printf("字符串%s 从第 %d 个字符翻转后的结果为: %s\n",str1,0,pstr);

}

int main(void)
{
    test();
    return 0;
}

测试用例:



版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35396127/article/details/79962108

剑指Offer面试题41:求和为s的两个数字;求和为s的连续正数序列 Java实现

题目一:输入一个递增排序的数组和一个数字s,在数组中找两个数,使得他们的和刚好是s.如果有多对数字的和等于s,则输出任意一对即可。例如,输入数组{1,2,4,7,11,15}和数字15,则输出4和11...
  • gg543012991
  • gg543012991
  • 2016-09-25 16:40:44
  • 707

剑指Offer面试题41(Java版):和为s的两个数字VS和为s的连续正数序列

题目一:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多个数字的和等于s,输出任意一对即可。 例如输入数组{1,2,4,7,11,15}和数字15.由于4+11...
  • jsqfengbao
  • jsqfengbao
  • 2015-08-10 19:47:11
  • 1546

剑指Offer面试题42:翻转单词顺序;左旋转字符串 Java实现

题目一:输入一个英文句子,翻转句子中单词的顺序,但单词内字符串的顺序不变。例如输入字符串:“I am a student”,则输出“student a am I”. 算法分析: 算法1...
  • gg543012991
  • gg543012991
  • 2016-09-25 20:20:19
  • 1152

剑指offer面试题54 表示数字的字符串(java实现)

解题思路: 1.在数值之前可能有一个表示正负的‘+’或者‘-’,接下来是若干个0到9的数位表示数值的整数部分(在某些小数里可能没有数值的整数部分)。如果数值是一个小数,那么在小数点后面可能会有若干个...
  • u013398759
  • u013398759
  • 2017-07-19 15:10:33
  • 222

《剑指offer》和为S的两个数字

【 声明:版权所有,转载请标明出处,请勿用于商业用途。  联系信箱:libin493073668@sina.com】 题目链接:http://www.nowcoder.com/p...
  • libin1105
  • libin1105
  • 2015-09-12 22:48:30
  • 629

剑指Offer 42题 翻转单词顺序 Java版

package test; public class ReverseSentence { public String reverse(String sentence){ if(senten...
  • yuhushangwei
  • yuhushangwei
  • 2016-10-04 02:38:58
  • 318

《剑指Offer》面试题:将字符串转换为整数

题目 题目:把字符串转化为整数 ,若输入无效,则返回0且将标志位设为true 自己以前在一些书上面看到过关于 字符串转化为整数的例子,心中有点印象,知道要考虑一些特殊情况。今天决定写下这段代码,...
  • u010412719
  • u010412719
  • 2015-08-30 20:02:32
  • 1673

剑指offer第十七题之第二十六题(java详解)

目录 第17题:合并两个排序的链表 第18题:树的子结构 第19题:二叉树的镜像 第20题:顺时针打印矩阵 第21题:包含min函数的栈 第22题:栈的压入、弹出序列 第23题:从上往下打印二叉树 第...
  • jiaohanhan
  • jiaohanhan
  • 2017-05-27 15:22:54
  • 233

剑指offer48--判断字符串的数值形式

实现一个函数来判断字符串是否是数值的形式(包括小数、整数和指数等)
  • jinhuoxingkong
  • jinhuoxingkong
  • 2016-07-22 14:29:34
  • 536

【剑指offer-Java版】49把字符串转换为整数

字符串转换为整数 : atoi可能的输入: 1 带符号数 2 无符号数 3 零 4 空指针 5 超出表示范围 – 暂时仅仅是直接退出且设置最小 – 可以考虑此时抛个异常 6 非法输入,比如...
  • Sugar_Z_
  • Sugar_Z_
  • 2016-04-27 09:48:55
  • 1215
收藏助手
不良信息举报
您举报文章:【剑指offer】第五十七题(和为 s 的两个数字) 和 第五十八题(翻转字符串)
举报原因:
原因补充:

(最多只允许输入30个字)