编程之旅-Day10

目录

Day10-学习内容

1.剑指Offer

面试题25:合并两个排序的链表

面试题43:整数中1出现的次数

2.Leetcode

例1:求最短变换序列的长度

例2:重排链表

3.2017年校招真题

例1:下厨房

例2:将n变为Fibonacci数的最小步数

4.校招真题-单选题


 

1.剑指Offer

面试题25:合并两个排序的链表

题目描述:

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

考察点:代码的鲁棒性,是否考虑空链表的情况。

代码:

class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1==nullptr){
            return pHead2;
        }
        else if(pHead2==nullptr){
            return pHead1;
        }
        ListNode* pMerge=nullptr;
        if(pHead1->val<=pHead2->val){
            pMerge=pHead1;
            pMerge->next=Merge(pHead1->next,pHead2);
        }
        else{
            pMerge=pHead2;
            pMerge->next=Merge(pHead1,pHead2->next);
        }
        return pMerge;
    }
    
};

面试题43:整数中1出现的次数

题目描述:

求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

思路:1.累加1到n每个整数1出现的次数,时间复杂度是O(nlogn)。

           2.找出数字规律,利用递归快速求解,时间复杂度是O(logn)。

解析:1.数字转换为字符数组

 char str[50];
 sprintf(str,"%d",n);

 int first=*str-'0';

int sprintf(char *str, const char *format, ...) 发送格式化输出到 str 所指向的字符串。

         2.atoi():将字符串转换为整型值。

https://www.cnblogs.com/bluestorm/p/3168719.html

         3.static_cast是一个强制类型转换操作符

https://www.cnblogs.com/QG-whz/p/4509710.html

代码:

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        if(n<=0) return 0;
        char str[50];
        sprintf(str,"%d",n);
        return NumberOf1(str);
    }
    int NumberOf1(const char *str){
        if(!str||*str<'0'||*str>'9'||*str=='\0'){
            return 0;
        }
        int first=*str-'0';
        unsigned int length=static_cast(strlen(str));
        if(length==1&&first==0){
            return 0;
        }
        if(length==1&&first>0){
            return 1;
        }
        int numFirstDigit=0;
        if(first>1){
            numFirstDigit=PowerBase10(length-1);
        }
        else if(first==1){
            numFirstDigit=atoi(str+1)+1;
        }
        int numOtherDigit=first*(length-1)*PowerBase10(length-2);
        int numRecursive=NumberOf1(str+1);
        return numFirstDigit+numOtherDigit+numRecursive;
    }
    int PowerBase10(unsigned int n){
        int result=1;
        for(int i=0;i

 

2.Leetcode

例1:求最短变换序列的长度

题目描述:

Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that: 

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the dictionary

For example, 

Given:
start ="hit"
end ="cog"
dict =["hot","dot","dog","lot","log"] 

As one shortest transformation is"hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length5. 

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.

思路:

1.先把字典里面的start删掉,然后插入end。 

2.每次找出与队头元素只相差一个字符的单词插入队列,队列一开始只有start。

3.访问过的单词不再访问,故需使用一个deletelist记录已访问的单词用于之后从字典中将其删除。

4.当队列里面包含end单词时停止循环,此长度就是最短长度。

代码:

class Solution {
public:
    int ladderLength(string start, string end, unordered_set &dict) {
        dict.insert(end);
        dict.erase(start);
        queue q;
        q.push(start);
        int length=0;
        while(q.size()>0){
            length++;
            int queueLength=q.size();

            for(int i=0;i deleteList;
                for(unordered_set::iterator iter=dict.begin();iter!=dict.end();iter++){
                    int d=distance(start,*iter);
                    if(d==1){
                        q.push(*iter);
                        deleteList.push_back(*iter);
                    }
                }
                for(int i=0;i

例2:重排链表

题目描述:

Given a singly linked list LL 0→L 1→…→L n-1→L n,
reorder it to: L 0→L n →L 1→L n-1→L 2→L n-2→… 

You must do this in-place without altering the nodes' values. 

For example,
Given{1,2,3,4}, reorder it to{1,4,2,3}. 

思路:快慢指针找到中间节点,然后将后面的链表反转(前插法),合并链表,注意题目要求就地解决,即不能用辅助存储空间。

代码:

class Solution {
public:
    void reorderList(ListNode *head) {
        if(head==nullptr||head->next==nullptr||head->next->next==nullptr){
            return;
        }
        ListNode *fast=head;
        ListNode *low=head;
        while(fast->next!=nullptr&&fast->next->next!=nullptr){   //快慢指针找中间节点
            fast=fast->next->next;
            low=low->next;
        }
        fast=low->next;
        low->next=nullptr;
        while(fast!=nullptr){    //对low后面的部分逆序
            ListNode *temp=fast->next;
            fast->next=low->next;
            low->next=fast;
            fast=temp;
        }       
        ListNode *p=head;
        ListNode *q=low->next;
        while(q!=nullptr&&p!=nullptr){    //合并low前后两部分
            low->next=q->next;
            q->next=p->next;
            p->next=q;
            p=q->next;
            q=low->next;    
        }
    }
};

3.2017年校招真题

例1:下厨房

题目描述:

牛牛想尝试一些新的料理,每个料理需要一些不同的材料,问完成所有的料理需要准备多少种不同的材料。

  输入描述:

每个输入包含 1 个测试用例。每个测试用例的第 i 行,表示完成第 i 件料理需要哪些材料,各个材料用空格隔开,输入只包含大写英文字母和空格,输入文件不超过 50 行,每一行不超过 50 个字符。

输出描述:
输出一行一个数字表示完成所有料理需要多少种不同的材料。

示例1

  输入

BUTTER FLOUR
HONEY FLOUR EGG

输出
4

解析:vector相关函数   https://www.cnblogs.com/aminxu/p/4686332.html

代码:

#include 
#include 
#include 

using namespace std;

int main(){
    string food;
    vector vecfood;
    while(cin>>food){
        auto it=find(vecfood.begin(),vecfood.end(),food);
        if(it==vecfood.end()){
            vecfood.push_back(food);
        }
    }
    cout<

例2:将n变为Fibonacci数的最小步数

题目描述:

Fibonacci数列是这样定义的:
F[0] = 0
F[1] = 1
for each i ≥ 2: F[i] = F[i-1] + F[i-2]
因此,Fibonacci数列就形如:0, 1, 1, 2, 3, 5, 8, 13, ...,在Fibonacci数列中的数我们称为Fibonacci数。给你一个N,你想让其变为一个Fibonacci数,每一步你可以把当前数字X变为X-1或者X+1,现在给你一个数N求最少需要多少步可以变为Fibonacci数。

  输入描述:

输入为一个正整数N(1 ≤ N ≤ 1,000,000)

输出描述:
输出一个最小的步数变为Fibonacci数"

示例1

 输入

15

输出
2

思路:分别求出比n大的最小fabonacci数和比n小的最大fabonacci数,n与这两个数差的最小值即为最小步数。

代码:

#include 

using namespace std;

int main(){
    int n,upperlim,lowerlim,f;
    int f1=0;
    int f2=1;
    cin>>n;
    while(1){
        f=f1+f2;
        f1=f2;
        f2=f;
        if(f

4.校招真题-单选题

例1:阿里巴巴国际站的股票代码是1688,这个数字具有这样的特性,首先是个首位为1的4位数,其次恰巧有且仅有1个数字出现了两次。类似的数字还有:1861,1668等。这样的数字一共有()个。(F)

A.144 B.180 C.216 D.270 E.288 F.432

解析:

分两种情况讨论: 

(1)若这个四位数的重复数字为1,那么首先从三个空位中选出一个给1,第二步从剩下9个可选数字中选出2个有序的排列到剩下的两个空位中去,那么有C(1,3)*A(2,9)=3*(9!/(9-2)!)=3*9*8=216种可能; 

(2)若这个四位数的重复数字不为1,那么首先从9个可选数字中选出一个作为重复数字(C(1,9)),并放到三个空位中的两个(这两个数字相同,故只涉及组合)(C(2, 3)),然后从剩下8个数字中选出一个(它的位置在重复数字确定后就自然固定了,不可选)即可,故有C(1,9)*C(2, 3)*C(1, 8)=216种可能。 

总共:216+216=432

 

例2:工程师M发明了一种游戏:M将一个小球随机放入完全相同的三个盒子中的某一个,玩家选中装有球的盒子即获胜;开始时M会让玩家选择一个盒子(选择任何一个获胜概率均为1/3);玩家做出选择后,M会打开没有被选择的两个盒子中的一个空盒,此时M会询问玩家是否更改选择(可以坚持第一次选择,也可以选择另一个没有打开的盒子),下列叙述正确的有(E)。

A.改选后,玩家获胜的概率还是1/3

B.若不改选,玩家的获胜概率是1/2

C.无论怎么选择,获胜的概率都是1/2

D.坚持原来的选择获胜概率更高

E.选择另一个没有被打开的盒子获胜概率更高

F.获胜概率取决于随机因素(如小球的实际位置)

解析:

三个盒子A,B,C。其中,1表示有球,0表示没球。

选取三个盒子概率都一样。我们假设选择了A。

此时有三种情况如下所示:

情况一:我选中了有球的盒子,我更换的话将失败,不更换的话将成功。

情况二:我选中了没球的盒子,我更换的话将成功,不更换的话将失败。

情况三:我选中了没球的盒子,我更换的话将成功,不更换的话将失败。

综上,我们发现更换了成功的概率是2/3;二不更换成功的概率是1/3。

因此选择E。

 

例3:下列不是进程间的通信方式的是(B)

A.管道 B.回调 C.共享内存 D.消息队列 E.socket F.信号量

解析:

管道:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
回调: 是一种编程机制
共享内存:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。   
消息队列:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
socket:socket也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
信号量:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
 

例4:已知IBM的PowerPC是big-endian字节序列而Intel的X86是little-endian字节序,如果在地址啊存储的整形值时0x04030201,那么地址为a+3的字节内存储的值在PowerPC和Intel X86结构下的值分别是?(A)

A.1 4 B.1 3 C.4 1 D.3 1 E.4 4 F.1 1

解析:大端从大地址开始存储,小端相反,两者都是从数据低位开始存起; 假设从上至下地址递增,则

PowerPC(大):                    Intel X86(小):

04                                            01                    低

03                                            02                     

02                                            03                     

01                                            04                     高

a+3指向最大的地址,所以分别为1 4

 

例5:在TCP/IP建立连接过程中,客户端或服务器的状态转移说法错误的是?(D)

 A.经历SYN_RECV状态

 B.经历SYN_SEND状态

 C.经历ESTABLISHED状态

 D.经历TIME_WAIT状态

 E.服务器在收到syn包时将加入半连接队列

 F.服务器收到客户端的ack包后将从半连接队列删除

解析:TIME_WAIT是断开连接时的状态(属于第四次握手)

 

例6:已知一棵二叉树的先序和中序遍历序列如下:先序:A、B、C、D、E、F、G、H、I,J中序:C、B、A、E、F、D、I、H、J、G其后序遍历序列为:(E)

 A.C、B、D、E、A、G、I、H、J、F

 B.C、B、D、A、E、G、I、H、J、F

 C.C、E、D、B、I、J、H、G、F、A

 D.C、E、D、B、I、H、J、G、F、A

 E.C、B、F、E、I、J、H、G、D、A

 F.C、B、F、E、I、H、J、G、D、A

参考:

https://blog.csdn.net/Cassiel_Paris/article/details/80203633

https://www.cnblogs.com/chongerlishan/p/5971024.html

 

你可能感兴趣的:(计算机,编程,算法,数据结构,算法,数据结构)