Day10-学习内容
1.剑指Offer
面试题25:合并两个排序的链表
面试题43:整数中1出现的次数
2.Leetcode
例1:求最短变换序列的长度
例2:重排链表
3.2017年校招真题
例1:下厨房
例2:将n变为Fibonacci数的最小步数
4.校招真题-单选题
题目描述:
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
考察点:代码的鲁棒性,是否考虑空链表的情况。
代码:
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;
}
};
题目描述:
求出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
题目描述:
Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:
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:
思路:
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
题目描述:
Given a singly linked list L: L 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;
}
}
};
题目描述:
牛牛想尝试一些新的料理,每个料理需要一些不同的材料,问完成所有的料理需要准备多少种不同的材料。
输入描述:
每个输入包含 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<
题目描述:
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
例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