作者:寒小陽
時間:2013年9月。
出處:http://blog.csdn.net/han_xiaoyang/article/details/11924701。
聲明:版權所有,轉載請注明出處,謝謝。
題目是網上找的,答案博主自己做的,有不當之處或者有更好的方法歡迎留言!
一堆硬幣,一個機器人,如果是反的就翻正,如果是正的就拋擲一次,無窮多次後,求正反的比例哈爾濱站)
典型的數學概率題(好吧,說明數學還是很重要滴,大家去筆試面前還是鞏固一下概率比較好,恩),這裡假設無窮多次後正面朝上的比例為x,則反面朝上的比例為1-x;則再投遞一次,根據題意,正面朝上的概率的就變成1-x+(1/2*x),,反面朝上的概率變為1/2*x.因為此時已經達到平衡的狀態,則該次投遞前後概率應該不變,即1-x=1/2*x。解得x為2/3
k鏈表翻轉。給出一個鏈表和一個數k,比如鏈表1→2→3→4→5→6,k=2,則翻轉後2→1→4→3→6→5,若k=3,翻轉後3→2→1→6→5→4,若k=4,翻轉後4→3→2→1→5→6,用程序實現。
/*************************************************************************************************
/*首先,博主說明一下,博主不清楚k>鏈表長度的時候,題目的本意是讓我們怎麼處理的,博主這裡直接沒有做任何翻轉,將原鏈表返回了。
**************************************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
usingnamespace std;
//定義鏈表節點
struct Node{
int data;
Node *next;
};
//函數在給定頭結點和尾節點的情況下,對整個鏈表做翻轉
void ReverseLinkList(Node *head,Node *end){
if(head==NULL||end==NULL) return;
Node *pre=NULL,*cur=head,*stop=end->next;
while(cur!=stop){
Node* nxt=cur->next;
cur->next=pre;
pre=cur;
cur=nxt;
}
}
//k鏈表翻轉
Node* ReverseKLinkList(Node *head,int k){
if(head==NULL||k<=0) return NULL;
Node *cur=head;
for(int i=0;i<k-1;i++){
cur=cur->next;
if(cur==NULL)
break;
}
//在鏈表長度小於k的情形下,直接返回原鏈表
if(cur==NULL) return head;
Node* begin=cur->next,*end=begin;
Node* pre=head;
ReverseLinkList(head,cur);
while(begin!=NULL){
for(int i=0;i<k-1;i++){
end=end->next;
if(end==NULL)
break;
}
if(end==NULL){
pre->next=begin;
break;
}
else{
Node *nextbegin=end->next;
ReverseLinkList(begin,end);
pre->next=end;
pre=begin;
begin=end=nextbegin;
}
}
return cur;
}
int main(){
int a[]={0,,1,2,3,4,5,6,7,8,9,10,11};
Node* node[12];
for(int i=0;i<12;i++){
node[i]=new Node;
node[i]->next=NULL;
node[i]->data=a[i];
}
for(int i=0;i<11;i++){
node[i]->next=node[i+1];
}
Node *tmp=ReverseKLinkList(node[0],4);
for(;tmp!=NULL;tmp=tmp->next){
cout<<tmp->data<<endl;
}
system("pause");
return 0;
}
有ABCD死人要在夜裡過一座橋,他們通過這座橋分別需要耗時1,2,5,10分鐘,現在只有一只手電,過橋時必須要帶著手電,並且同時最多只能兩個人一起過橋。請問如何安排能夠讓四個人盡快都過橋。長沙站)
如果博主沒有記錯的話,這是騰訊幾年前考過的一道題,一到校招時,就發現各大公司筆試題抄來抄去,好吧,停止吐槽。這種智力題一向是博主這樣智力平庸人的硬傷,恩,直接上答案了。
第一步:A(1)和B(2)過橋,A(1)返回Cost:1+2s
第二步:C(5)和D(10)過橋,B(2)返回Cost:10+2s
第三步:A(1)和B(2)過橋Cost:2 s
總共耗時3+12+2=17s
有25匹馬,每匹馬都以恆定的速度賽跑,當然馬與馬之間的速度是不相等的,總共有5個賽道,就是說每輪最多只能有5個馬同時賽跑。問題是:要確定出跑的最快的前三名馬,需要最少多少輪比賽?長沙站)
不多說了,直接上答案吧。
總共需要7場
1)首先分5組 比賽5次
(ABCDE)決出
A1 A2 A3 A4 A5
B1 B2 B3 B4 B5
C1 C2 C3 C4 C5
D1 D2 D3 D4 D5
E1 E2 E3 E4 E5
2)再比賽1次
A1 B1 C1 D1 E1比賽
至少可以淘汰2組
假設 A1 > B1 > C1 > D1E1
則 最快的必然是 A1 A2 A3 B1 B2 C1中的3批
A1已經確定有
3)則最後一場對A2 A3 B1 B2 C1進行比較,選出前2名
在有團購之前,大家都是現場買門票的,公園的門票是5元;某天售票處開門時沒有准備零錢。假設一天來購票的一次有2N個人,其中有N個人有5元零錢,其它N個人只有10元面值的錢;假設每人只買一張票。請問任何人都不必為找零而等待的概率是多少?(長沙站)
這道題,好吧,博主的第一反應是:這是標准的Catalan數的應用吧!好吧,打算隨後拿一篇出來介紹下Catalan數),博主奇怪的是,美團今年的校招題,腫麼數學題這麼多-_-||
隱隱約約記得這道題貌似《編程之美》上也有,為了將問題簡單化,將持有5元的人看成1,持有10元的人看成0,這樣,只要滿足:在任何0位置之前,1的數目多於0的數目,就能滿足要求,則該題求解的為滿足要求的排列占全部排列的比例。
1)求2n個1和0的全排列數目:C(2n,n),即從2n個位置中選取n放置0或者1)。
2)求取不滿足要求的組合數合法的組合數不好求):
不滿足要求的組合數的特點:總能找到一個位置K,使得0的數目比1的數目多1。那麼很明顯,k後面的0的數目比1的數目要少1.為什麼要找位置k?因為,我要讓前面K個位置0、1排列不管怎麼排列都不合法)
此後,我們關注k位置後面的排列:因為k後面的排列中,明顯0比1少,那麼我們可以將0和1互換為什麼要互換?首先,0、1互換後,兩種排列方式的總數目是不變的,其次,互換後的排列中0比1多1個,那麼不管怎麼排列,都不合法),這樣互換後2n個數的排列不管怎麼排列都不合法值得注意的是,互換後的組合排列數目,和互換前的是相同的,因為前面的排列不變且後面排列組合方式的數目一樣。
現在來計算互換後排列的數目:互換後排列的數目中0為n+1個,1為n-1個,那麼組合數就相當於從2n個位置選取n+1個位置放0,即為C2n,n+1)
所求結果為( C(2n,n)-C(2n,n+1) )/ C(2n,n)
有一個函數“int f(int n)”,請編寫一段程序測試函數f(n)是否總是返回0,並添加必要的注釋和說明。
這一題博主木有明確的思路,感覺上黑盒測試的話只能從INT_MIN到INT_MAX全部測試了,或者加上隨機算法,抽樣檢測。大家有好的方法歡迎留言。
用你熟悉的語言編寫程序用兩個棧(Stack)模擬隊列(Queue)的先進先出操作,僅實現add、remove方法即可。長沙站)
非常非常經典的一道老題了,假設兩個棧s1和s2,且都為空。可以認為棧s1提供入隊列的功能,棧s2提供出隊列的功能。
1)入隊列:入棧s1。
2)出隊列:如果棧s2不為空,直接彈出棧s2的數據;如果棧s2為空,則依次彈出棧s1的數據,放入棧s2中,再彈出棧s2的數據。
#include <iostream>
#include <stack>
usingnamespace std;
template<class T>
struct MyQueue
{
void add(T &t)
{
s1.push(t);
}
T front()
{
if(s2.empty())
{
if(s1.size() == 0) throw;
while(!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
}
return s2.top();
}
void remove()
{
if(s2.empty())
{
while(!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
}
if(!s2.empty())
s2.pop();
}
stack<T> s1;
stack<T> s2;
};
int main()
{
MyQueue<int> mq;
for(int i=0; i< 10; ++i)
{
mq.add(i);
}
for(i=0; i< 10; ++i)
{
cout<<mq.front()<<endl;
mq.remove();
}
return 0;
}
編寫函數,獲取兩段字符串的最長公共子串的長度,例如:
S1 = GCCCTAGCCAGDE
S2 = GCGCCAGTGDE
這兩個序列的最長公共字串為GCCAG,也就是說返回值為5.(長沙站)
說實話,一直以來見著的都是讓求最長公共子序列,突然讓求最長公共字串,反倒有些不習慣了,總覺得考最長公共子序列更合理一點吧,好吧,又看了一遍題,確實是求最長公共子串的長度。
為了說清楚一點,就用上面的例子吧,我們來列一張表,如下:
G C C C T A G C C A G D E
G 1 0 0 0 0 0 1 0 0 0 1 0 0
C 0 1 1 1 0 0 0 1 1 0 0 0 0
G1 0 0 0 0 0 1 0 0 0 1 0 0
C 0 1 1 1 0 0 0 1 1 0 0 0 0
C 0 1 1 1 0 0 0 1 1 0 0 0 0
A 0 0 0 0 0 1 0 0 0 1 0 0 0
G1 0 0 0 0 0 1 0 0 0 1 0 0
T 0 0 0 0 1 0 0 0 0 0 0 0 0
G1 0 0 0 0 0 1 0 0 0 1 0 0
D 0 0 0 0 0 0 0 0 0 0 0 1 0
E 0 0 0 0 0 0 0 0 0 0 0 0 1
則最長公共子串GCCAG為上圖中標出的最長斜對角線
博主在下面先寫一種最容易看懂的方法,這種方法的空間復雜度還可以再優化,不過這個問題,之後等博主寫到最長公共子序列、最長公共字串和最長遞增子序列專題的時候再寫吧。
#include<stdio.h>
#include<string.h>
#define N 100
//LCS問題:即求兩個字符串最長公共子串的問題,這裡返回了公共字串,如果只求最長公共字串長度的話,之後有個簡單的程序,其實就是裡面的一部分
char *LCS(char *a,char *b)
{
int len_a = strlen(a); //獲取字串的長度
int len_b = strlen(b);
char *p;
int c[N][N] = {0}; //矩陣c記錄兩串的匹配情況
int start,end,len,i,j; //start表明最長公共子串的起始點,end表明最長公共子串的終止點
end = len = 0; //len表明最長公共子串的長度
for(i=0;i<len_a;i++) //串開始從前向後比較
{
for(j=0;j<len_b;j++)
{
if(a[i] == b[j])
if(i == 0 || j == 0)
c[i][j] = 1;
else
c[i][j] = c[i-1][j-1] + 1;
if(c[i][j] > len)
{
len = c[i][j];
end = j;
}
}
}
start = end - len + 1;
p = (char *)malloc(len+1); //數組p記錄最長公共子串
for(i=start;i<=end;i++)
p[i-start] = b[i];
p[len] = '\0';
for(j=0;j<len_b;j++)
{
for(i=0;i<len_a;i++)
printf("%2d",c[i][j]);
printf("\n");
}
return p;
}
int main(int argc,char *argv[])
{
char str1[N],str2[N];
printf("請輸入字符串1:");
gets(str1);
printf("請輸入字符串2:");
gets(str2);
printf("最長子串為:%s\n",LCS(str1,str2));
return 0;
}
//只求最長公共字串長度
int LCS(char *a,char *b)
{
int len_a = strlen(a); //獲取字串的長度
int len_b = strlen(b);
char *p;
int c[N][N] = {0}; //矩陣c記錄兩串的匹配情況
int start,end,len,i,j; //start表明最長公共子串的起始點,end表明最長公共子串的終止點
end = len = 0; //len表明最長公共子串的長度
for(i=0;i<len_a;i++) //串開始從前向後比較
{
for(j=0;j<len_b;j++)
{
if(a[i] == b[j])
if(i == 0 || j == 0)
c[i][j] = 1;
else
c[i][j] = c[i-1][j-1] + 1;
if(c[i][j] > len)
{
len = c[i][j];
end = j;
}
}
}
return len;
}
有100盞燈,從1~100編上號,開始時所有的燈都是關著的。
第一次,把所有編號是1的倍數的燈的開關狀態改變一次;
第二次,把所有編號是2的倍數的燈的開關狀態改變一次;
第三次,把所有編號是3的倍數的燈的開關狀態改變一次;
以此類推,直到把所有編號是100的倍數的燈的開關狀態改變一次。
問,此時所有開著的燈的編號。哈爾濱站)
由於最開始燈是滅的,那麼只有經過奇數次改變開關狀態的燈是亮的。根據題意可知一個數字有多少約數就要開關多少次,所以最後亮著的燈的數學解釋就是:燈的編號有奇數個不同的約數。
一個數的約數按出現的奇偶個數分為以下兩種:
q 約數是成對出現的,比如8的約數對為:1,8)、2,4)。
q 約數是單個出現的,比如36的約數對為:1,36)、2,18)、3,12)、4,9)、6)。
可以看出6自己單獨是36的約數,而不是和別的數連在一起。所以只有平方數才會有奇數個整型約數,才滿足本題的要求。從1到100的平方數為:
1,4,9,16,25,36,49,64,81,100。
所以只有這些燈是亮的。
本文出自 “驿落黃昏” 博客,請務必保留此出處http://yiluohuanghun.blog.51cto.com/3407300/1301200