百度一面
1、給定一個字符串比如“abcdef”,要求寫個函數變成“defabc”,位數是可變的。
別人的方法:這個比較簡單,我用的是strcpy和memcpy,然后他問有什么優化的辦法,我就不知道了。
我的方法:
用兩個指針*front,*rear分別指向字符串的第一個字符和最后一個字符。
以下是代碼:
#include<stdio.h> #include<string.h> int main(void){ char s[] = "abcdefa";//如果是char *s ,則后面不能修改其指向的內容。原因是: //char指針指向文本字符串,可以認為char指針是指向const對象的指針;char數組名,可以認為是常量指針,不允許修改指向 char *front,*rear = s; while(*rear != NULL) rear ++; rear--; while(front != rear){ if(*front != *rear){ //如果兩個字符相等,則不需要互換 char temp = *front; *front = *rear; *rear = temp; } front++; rear--; } printf("%s",&s); return 0; }
2、socket過程就是socket的server和client整個流程寫下來,這個還是沒啥問題的。
詳見:http://blog.csdn.net/heyutao007/article/details/6588302
3、數據結構二叉樹的遍歷,給了個二叉樹,前序、中序、后序寫出來,這個沒什么難度。
4、樹的層次遍歷,這個開始真忘了,想了半天才想起來用隊列。然后他又讓我詳細寫出入隊出隊的過程,總之還是搞定了。
這顆二叉樹的層次遍歷的過程:假設一個隊列Q,首先根節點A入隊列,接着取對頭元素,即A,將A的子節點B、C先后入隊列,再次取對頭元素,即B,然后將B的子節點D、#入隊列。重復取出對頭元素,將對頭元素入隊列的過程。直到隊列中的數據為空,遍歷結束。
5、兩圓相切轉圏問題——一個小圓半徑是1厘米,一個大圓半徑是5厘米,小圓沿着大圓轉圈,請問要轉幾圈可以轉完大圈?這個問題在行測題做過,就是公轉自轉的問題,不管大小圓半徑是多少,外切轉圏要轉R/r+1圏,內切轉圏轉R/r-1圈。
百度二面
1、二叉樹的前序遍歷的遞歸和非遞歸的可執行程序。
遞歸容易實現。
非遞歸的實現需要借助棧來實現
//二叉樹的遍歷 //首先是遞歸實現: //先序遍歷 #include <stdio.h> #include "malloc.h" //定義二叉樹的節點 typedef struct BiTNode{ char data; struct BiTNode *lchild;//左子樹 struct BiTNode *rchild;//右子樹 }BiTNode,*BiTree; //先序建立二叉樹 BiTree createBiTree(){ char ch; BiTree T; scanf("%c",&ch); if(ch=='#'){ T = NULL; printf("Null"); } else{ T = (BiTree)malloc(sizeof(BiTNode)); T->data = ch; T->lchild = createBiTree(); T->rchild = createBiTree(); } return T;//返回根節點 } //前序遍歷(遞歸實現) void preOrder(BiTNode *root){ if(root != NULL){ printf("%c,",root->data); preOrder(root->lchild); preOrder(root->rchild); } } //前序遍歷(非遞歸實現) void preOrder2(BiTNode *root){ //初始化棧 stack *s = (stack *)malloc(sizeof(stack)); initStack(s); BiTNode *p = root;//遍歷指針 while(p || !isEmpty(s)){ if(p){ printf("%d ",p->data);//訪問父節點信息 push(s,p);//將父節點入棧 p = p->lchild;//遍歷左子樹 }else{ BiTNode *father = pop(s);//出棧的是p結點父節點 p = father->rchild;//遍歷右子樹 } } } //定義棧 typedef struct stack{ BiTNode nodes[20]; int size; int top;//指向棧頂元素,初始值為-1 }stack; //初始化stack void initStack(stack *stack){ stack->size = 0; stack->top = -1; } //判斷棧是否為空 bool isEmpty(stack *stack){ return stack->size==0?true:false; } //獲取棧大小 int getSize(stack *stack){ return stack->size; } //入棧 void push(stack *stack,BiTNode *node){ if(stack->size<20){ stack->top++; stack->nodes[stack->top] = *node; } } //出棧 BiTNode* pop(stack *stack){ if(stack->top >= -1){ return &stack->nodes[stack->top]; } return NULL; } //中序遍歷 void inOrder(BiTNode *root){ if(root != NULL){ inOrder(root->lchild); printf("%c,",root->data); inOrder(root->rchild); } } //后序遍歷 void postOrder(BiTNode *root){ if(root != NULL){ postOrder(root->lchild); postOrder(root->rchild); printf("%c,",root->data); } }
2、寫出快速排序的實現代碼,一個是字符串拼接函數的實現strcat(),還有大數相乘,都是基本題。
2.1、快速排序:
void quick_sort1(int s[], int l, int r) { if (l < r) { int i = AdjustArray(s, l, r);//先成挖坑填數法調整s[] quick_sort1(s, l, i - 1); // 遞歸調用 quick_sort1(s, i + 1, r); } } int AdjustArray(int s[], int l, int r) //返回調整后基准數的位置 { int i = l, j = r; int x = s[l]; //s[l]即s[i]就是第一個坑 while (i < j) { // 從右向左找小於x的數來填s[i] while(i < j && s[j] >= x) j--; if(i < j) { s[i] = s[j]; //將s[j]填到s[i]中,s[j]就形成了一個新的坑 i++; } // 從左向右找大於或等於x的數來填s[j] while(i < j && s[i] < x) i++; if(i < j) { s[j] = s[i]; //將s[i]填到s[j]中,s[i]就形成了一個新的坑 j--; } } //退出時,i等於j。將x填到這個坑中。 s[i] = x; return i; }
3、歸並排序的實現。
public void MergerSort(int[] v, int first, int last) { if (first + 1 < last) { int mid = (first + last) / 2; MergerSort(v, first, mid); MergerSort(v, mid, last); Merger(v, first, mid, last); } } public void Merger(int[] v, int first, int mid, int last) { Queue<int> tempV = new Queue<int>(); int indexA, indexB; //設置indexA,並掃描subArray1 [first,mid] //設置indexB,並掃描subArray2 [mid,last] indexA = first; indexB = mid; //在沒有比較完兩個子標的情況下,比較 v[indexA]和v[indexB] //將其中小的放到臨時變量tempV中 while (indexA < mid && indexB < last) { if (v[indexA] < v[indexB]) { tempV.Enqueue(v[indexA]); indexA++; } else { tempV.Enqueue(v[indexB]); indexB++; } } //復制沒有比較完子表中的元素 while (indexA < mid) { tempV.Enqueue(v[indexA]); indexA++; } while (indexB < last) { tempV.Enqueue(v[indexB]); indexB++; } int index = 0; while (tempV.Count > 0) { v[first+index] = tempV.Dequeue(); index++; } }
4、文件按a~z編號,aa~az,ba~bz...za...zz...aaa...aaz,aba~abz...這樣的方法進行編號。給定任意一個編號,輸出文件是第幾個文件。並寫出測試方法。簡單,把編號看成26進制,這題就是一個十進制和26進制的進制轉換問題了。
5、編程:兩個鏈表,按升序排序,合並后仍按升序,不准用遞歸,並求復雜度
百度電面:
1、談談你對數據庫中索引的理解
解答:
索引就是加快檢索表中數據的方法。數據庫的索引類似於書籍的索引。在書籍中,索引允許用戶不必翻閱完整個書就能迅速地找到所需要的信息。在數據庫中,索引也允許數據庫程序迅速地找到表中的數據,而不必掃描整個數據庫。
2、現在普通關系數據庫用得數據結構是什么類型的數據結構
關系模型(二維表)。
3、索引的優點和缺點
索引的優點 1.創建唯一性索引,保證數據庫表中每一行數據的唯一性 2.大大加快數據的檢索速度,這也是創建索引的最主要的原因 3.加速表和表之間的連接,特別是在實現數據的參考完整性方面特別有意義。 4.在使用分組和排序子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。 5.通過使用索引,可以在查詢的過程中使用優化隱藏器,提高系統的性能。
索引的缺點 1.創建索引和維護索引要耗費時間,這種時間隨着數據量的增加而增加 2.索引需要占物理空間,除了數據表占數據空間之外,每一個索引還要占一定的物理空間,如果要建立聚簇索引,那么需要的空間就會更大 3.當對表中的數據進行增加、刪除和修改的時候,索引也要動態的維護,降低了數據的維護速度
4、session、cookie和cache的區別是什么
詳見:http://blog.csdn.net/lonelyrains/article/details/7838074
5、如果有幾千個session,怎么提高效率?
將session存儲在數據庫中
6、session是存儲在什么地方,以什么形式存儲的?
| 方式 | 優點 | 缺點 | 應用 | |
| 存儲在本地機器內存中 | 速度讀取快 | 容易丟失 | 小型網站 | |
| 存儲在別的電腦中 | 不消耗本地資源 | 如果網絡不通,則Session讀取不到 | 大的網站 | |
| 存儲在數據庫中 | 存儲量大 | 速度慢 | 用戶很多的網站 |
新浪技術部筆試題
一、數據結構和算法 1、簡述什么是hashtable,如何解決hash沖突 2、什么叫二叉樹,滿二叉樹,完全二叉樹
4、數組和鏈表有什么區別,分別用在什么場合
數組和鏈表都是線性表,但數組是一組元素有序地存儲在連續的內存單元中,而鏈表的節點元素存儲的內存單元並不是連續的。
由於存儲性質,導致數組的查找可根據下標直接定位,而鏈表的查找需要遍歷,因此查找的效率數組比鏈表要高,而插入和刪除一個元素,數組需要平均移動二分之一的元素,而鏈表可以直接通過斷鏈和指針實現插入和刪除。
對於樹的操作一般用到鏈表,對於圖的操作一般用到數組。
數組應用場景:
1、注重存儲密度;
2、經常做的運算是按序號訪問數據元素;
3、數組更容易實現,任何高級語言都支持;
4、構建的線性表較穩定。
鏈表應用場景:
1、對線性表的長度或者規模難以估計;
2、頻繁做插入刪除操作;
3、構建動態性比較強的線性表。
二、操作系統
1、什么叫虛擬內存
虛擬內存是計算機系統內存管理的一種技術。它使得應用程序認為它擁有連續的可用的內存(一個連續完整的地址空間),而實際上,它通常是被分隔成多個物理內存碎片,還有部分暫時存儲在外部磁盤存儲器上,在需要時進行數據交換。
2、塊設備和字符設備有什么區別
塊設備:。塊設備將信息存儲在固定大小的塊中,每個塊都有自己的地址。數據塊的大小通常在512字節到32768字節之間。塊設備的基本特征是每個塊都能獨立於其它塊而讀寫。磁盤是最常見的塊設備。
字符設備:字符設備按照字符流的方式被有序訪問,像串口和鍵盤就都屬於字符設備。
1.字符設備只能以字節為最小單位訪問,而塊設備以塊為單位訪問,例如512字節,1024字節等
2.塊設備可以隨機訪問,但是字符設備不可以
3.字符和塊沒有訪問量大小的限制,塊也可以以字節為單位來訪問
3、進程和線程的區別
4、簡述TCP網關連接交互細節
即TCP三次握手連接,四次握手斷開。
三、Lunix
1、寫出10個常用的linux命令和參數
1、返回上層目錄:cd ..;2、打印當前目錄:pwd;3、解壓tar.gz:tar -xzvf file.tar.gz 解壓tar:tar -xvf file.tar;4、強制刪除某個文件:rm -rf file;5、重命名/移動文件:mv /dir/file1 /dir2/file1;
更多詳見:http://os.51cto.com/art/201009/223806.htm
2、如何查看磁盤剩余空間
df -h1 3、如何查看端口是否被占用
4、如何查看某個進程所占用的內存
可分為動態查看和靜態查看,詳見:http://blog.csdn.net/sunlylorn/article/details/6215137
四、程序題(具體題目記不太清了)
1、用兩個線程實現1-100的輸出
public class Test1 { int num = 0; class addThread extends Thread { @Override public void run() { super.run(); while (true) { if (num < 100) addNum(); else break; } } } public synchronized void addNum() { System.out.println("num=" + num++); } public static void main(String[] args) { Test1 test = new Test1(); addThread t1 = test.new addThread(); addThread t2 = test.new addThread(); t1.start(); t2.start(); } }
2、把一個文件夾中所有01結尾的文件前十行內容輸出
package sina;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
public class Test2 {
public static void main(String[] args) {
print("e:/test");
}
private static void print(String pwd) {
File dir = new File(pwd);
File[] files = dir.listFiles();
for(int i=0;i<files.length;i++){
//遍歷每個文件
try {
RandomAccessFile rf = new RandomAccessFile(files[i], "r");
long len = rf.length();
long start = rf.getFilePointer();
long end = start+len;
rf.seek(end-2);
if(rf.read() == '0'){
rf.seek(end-1);
if(rf.read() == '1'){
//以01結尾的文件
readTop10Lines(files[i]);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 讀取文件前10行
* @param f
* @throws IOException
*/
private static void readTop10Lines(File f) throws IOException{
BufferedReader br = new BufferedReader(new FileReader(f));
String temp;
StringBuffer sb = new StringBuffer();
temp = br.readLine();
int count = 1;
while(temp != null && count<=10){
sb.append(temp);
temp = br.readLine();
count++;
}
System.out.println(sb.toString());
}
}
關於文件操作:http://blog.sina.com.cn/s/blog_507e84890100ch8q.html
思科一面:
1、C++和Java最大的區別是什么?
http://blog.chinaunix.net/uid-12707183-id-2918815.html
2、static、extern、global的作用?(再一次出現了static,上鏡率真高挖~)
http://blog.csdn.net/hackbuteer1/article/details/7487694
3、inline內聯函數是否占用運行時間?
不會占用運行時間。 在程序編譯時,編譯器將程序中出現的內聯函數的調用表達式用內聯函數的函數體來進行替換。由於在編譯時將內聯函數體中的代碼替代到程序中,因此會增加目標程序代碼量,進而增加空間開銷,而在時間開銷上不象函數調用時那么大,可見它是以目標代碼的增加為代價來換取時間的節省。
詳見:http://www.cnblogs.com/socrassi/archive/2009/09/09/1563002.html
關於C語言轉換為機器語言的過度:http://blog.csdn.net/chengocean/article/details/6250779。
思科二面:
1、進程和線程有什么區別?
進程是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。
詳見:http://jingyan.baidu.com/article/624e74598efcc834e9ba5a66.html
3、頁面的替換算法都有哪些?
1、理想頁面置換算法(OPT):這是一種理想的頁面替換算法,在實際中不可能實現。該算法的思想是:發生缺頁時,選擇以后永不使用或在最長時間內不再被訪問的內存頁面予以淘汰。
2、先進先出頁面置換算法(FIFO):選擇最先進入內存的頁面予以淘汰。
3、最近最久未使用算法(LRU):選擇在最近一段時間內最久沒有使用過的頁,把它淘汰。
4、最少使用算法(LFU):選擇到當前時間為止被訪問次數最少的頁轉換。
補充:磁盤調度算法。
詳見:http://blog.csdn.net/kennyrose/article/details/7532651
操作系統中常見的調度算法:http://blog.chinaunix.net/uid-25132162-id-361291.html
4、用戶態和內核態的區別?
當一個任務(進程)執行系統調用而陷入內核代碼中執行時,我們就稱進程處於內核運行態(或簡稱為內核態)。此時處理器處於特權級最高的(0級)內核代碼中執行。當進程處於內核態時,執行的內核代碼會使用當前進程的內核棧。每個進程都有自己的內核棧。當進程在執行用戶自己的代碼時,則稱其處於用戶運行態(用戶態)。即此時處理器在特權級最低的(3級)用戶代碼中運行。當正在執行用戶程序而突然被中斷程序中斷時,此時用戶程序也可以象征性地稱為處於進程的內核態。因為中斷處理程序將使用當前進程的內核棧。這與處於內核態的進程的狀態有些類似。
5、平面上N個點 沒兩個點都確定一條直線 求出斜率最大 那條直線所通過 兩個點 斜率不存在 情況不考慮 時間效率越高越好 解法:先把N個點按x排序。 斜率k最大值為max(斜率(point[i],point[i+1])) 0<=i<n-2。 復雜度Nlog(N)。 以3個點為例,按照x排序后為ABC,假如3點共線,則斜率一樣,假如不共線,則可以證明在AB或BC中,一定有一個點的斜率大於AC,一個點的斜率小於AC。
騰訊一面
1、關系型數據庫的特點
關系型數據庫,是指采用了關系模型來組織數據的數據庫。
關系模型是在1970年由IBM的研究員E.F.Codd博士首先提出的,在之后的幾十年中,關系模型的概念得到了充分的發展並逐漸成為主流數據庫結構的主流模型。
簡單來說,關系模型指的就是二維表格模型,而一個關系型數據庫就是由二維表及其之間的聯系所組成的一個數據組織。
關系模型中常用的概念:
- 關系:可以理解為一張二維表,每個關系都具有一個關系名,就是通常說的表名
- 元組:可以理解為二維表中的一行,在數據庫中經常被稱為記錄
- 屬性:可以理解為二維表中的一列,在數據庫中經常被稱為字段
- 域:屬性的取值范圍,也就是數據庫中某一列的取值限制
- 關鍵字:一組可以唯一標識元組的屬性,數據庫中常稱為主鍵,由一個或多個列組成
- 關系模式:指對關系的描述。其格式為:關系名(屬性1,屬性2, ... ... ,屬性N),在數據庫中成為表結構
關系型數據庫的優點:
- 容易理解:二維表結構是非常貼近邏輯世界的一個概念,關系模型相對網狀、層次等其他模型來說更容易理解
- 使用方便:通用的SQL語言使得操作關系型數據庫非常方便
- 易於維護:豐富的完整性(實體完整性、參照完整性和用戶定義的完整性)大大減低了數據冗余和數據不一致的概率
http://blog.csdn.net/robinjwong/article/details/18502195
2、父類的析構函數為什么要定義為虛函數
不定義為虛函數的話,delete父類只釋放了父類的內存空間,而子類的內存空間沒有釋放,造成了內存泄漏。而定義了虛函數則不會造成內存泄漏。
詳見:http://blog.csdn.net/qiurisuixiang/article/details/6926313
3、把一個字符串的大寫字母放到字符串的后面,各個字符的相對位置不變,不能申請額外的空間。 (比較難)
4、快排算法實現程序
http://blog.csdn.net/hackbuteer1/article/details/6568913
5、KMP算法實現程序
http://blog.csdn.net/hackbuteer1/article/details/7319115
6、override和overload的區別
java中,override:在繼承時,子類方法覆蓋父類方法;overload:同一個類中,方法名相同,但參數個數、順序和類型至少其中一個不同,則被視為不同的方法。
詳見http://www.cnblogs.com/whgw/archive/2011/10/01/2197083.html
7、編程並實現一個八皇后的解法
8、鏈表的歸並排序
騰訊二面:
1、在數據庫中如何創建一個表
CREATE TABLE table_name
(column_name data_type
{[NULL | NOT NULL]
[PRIMARY KEY | UNIQUE]}
2、創建后如何添加一個記錄、刪除一個記錄
用sql語句:
添加一個記錄:insert stu('id','name') with value(1,'he');
刪除一個記錄:delete from stu where id=1;
3、編寫C++中的兩個類 一個只能在棧中分配空間 一個只能在堆中分配。 (比較難)
4、請編寫實現malloc()內存分配函數功能一樣的代碼。
5、請編寫能直接實現strstr()函數功能的代碼。
KMP算法
6、已知: 每個飛機只有一個油箱, 飛機之間可以相互加油(注意是相互,沒有加油機) 一箱油可供一架飛機繞地球飛半圈, 問題:為使至少一架飛機繞地球一圈回到起飛時的飛機場,至少需要出動幾架飛機?(所有飛機從同一機場起飛,而且必須安全返回機場,不允許中途降落,中間沒有飛機場)
三架飛機足矣。。http://blog.sina.com.cn/s/blog_60c3c90f0100lkhs.html
7、static的作用——再一次出現~
http://blog.csdn.net/hackbuteer1/article/details/7487694
JAVA中的static 修飾符
1、static變量
按照是否靜態的對類成員變量進行分類可分兩種:一種是被static修飾的變量,叫靜態變量或類變量;另一種是沒有被static修飾的變量,叫實例變量。
兩者的區別是:
對於靜態變量在內存中只有一個拷貝(節省內存),JVM只為靜態分配一次內存,在加載類的過程中完成靜態變量的內存分配,可用類名直接訪問(方便),當然也可以通過對象來訪問(但是這是不推薦的)。
對於實例變量,沒創建一個實例,就會為實例變量分配一次內存,實例變量可以在內存中有多個拷貝,互不影響(靈活)。
所以一般在需要實現以下兩個功能時使用靜態變量:
在對象之間共享值時
方便訪問變量時
2、靜態方法
靜態方法可以直接通過類名調用,任何的實例也都可以調用,
因此靜態方法中不能用this和super關鍵字,不能直接訪問所屬類的實例變量和實例方法(就是不帶static的成員變量和成員成員方法),只能訪問所屬類的靜態成員變量和成員方法。
因為實例成員與特定的對象關聯!這個需要去理解,想明白其中的道理,不是記憶!!!
因為static方法獨立於任何實例,因此static方法必須被實現,而不能是抽象的abstract。
例如為了方便方法的調用,Java API中的Math類中所有的方法都是靜態的,而一般類內部的static方法也是方便其它類對該方法的調用。
靜態方法是類內部的一類特殊方法,只有在需要時才將對應的方法聲明成靜態的,一個類內部的方法一般都是非靜態的
3、static代碼塊
static代碼塊也叫靜態代碼塊,是在類中獨立於類成員的static語句塊,可以有多個,位置可以隨便放,它不在任何的方法體內,JVM加載類時會執行這些靜態的代碼塊,如果static代碼塊有多個,JVM將按照它們在類中出現的先后順序依次執行它們,每個代碼塊只會被執行一次。例如:
public class Test5 {
private static int a;
private int b;
static{
Test5.a=3;
System.out.println(a);
Test5 t=new Test5();
t.f();
t.b=1000;
System.out.println(t.b);
}
static{
Test5.a=4;
System.out.println(a);
}
public static void main(String[] args) {
// TODO 自動生成方法存根
}
static{
Test5.a=5;
System.out.println(a);
}
public void f(){
System.out.println("hhahhahah");
}
}
運行結果:
3
hhahhahah
1000
4
5
利用靜態代碼塊可以對一些static變量進行賦值,最后再看一眼這些例子,都一個static的main方法,這樣JVM在運行main方法的時候可以直接調用而不用創建實例。
8、寫string類的構造,析構,拷貝函數——這題大約出現過4次左右,包括編程和程序填空,程序員面試寶典上有這題,也算是個經典筆試題,出現幾率極大~
http://rsljdkt.iteye.com/blog/770072
微軟面試題
微軟面試題匯總 http://www.cnblogs.com/qlee/archive/2011/09/16/2178873.html 1、給你一個凸多邊形,你怎么用一條線,把它分成面積相等的兩部分 2、有一條數軸,上有一整數點s,點s兩側分別放了兩個機器人,不知道兩個機器人分別距離s的距離,兩機器人不能相互通信。 現在,給你以下指令: R(往右一格) L(往左一格) IF(S)是否在S點 GOTO A,跳到A代碼段。 設計一套指令給兩個機器人,讓兩個器機可以最終在某一點相遇。
3、怎么判斷兩棵二叉樹是否是同構的
4、按層次打印一個二叉樹
5、給你一個數n(最大為10000),怎么求其階乘
6、判斷兩個單鏈表是否有交叉
對於僅判斷相交不相交的話:判斷最后一個節點是否相同的辦法並不慢,如果兩個鏈表長度m,n 那么復雜度O(m+n),這是最優的復雜度
拓展:如何尋找交叉節點:
指針p、q分別遍歷鏈表a、b,假設q先到達NULL(即 假設a 比 b 長),此時從a的頭發出一個指針t,當p到達NULL時,從b的頭發出s,當s==t的時候即交點.
58同城面試題
一面:
1、set(底層基於紅黑樹實現)的操作;
list,set,map的用法和區別:http://www.cnblogs.com/I-am-Betty/archive/2010/09/06/1819486.html
java中treemap和treeset實現(紅黑樹):http://www.cnblogs.com/liqizhou/archive/2012/09/27/java%E4%B8%ADtreemap%E5%92%8Ctreeset%E5%AE%9E%E7%8E%B0%E7%BA%A2%E9%BB%91%E6%A0%91.html
hashtable和hashmap的區別:
2、手寫快排遞歸與非遞歸實現;
http://blog.csdn.net/hackbuteer1/article/details/6568913
3、KMP原理解釋
http://blog.csdn.net/hackbuteer1/article/details/7319115
4、聚類分類協同過濾算法;
http://blog.csdn.net/wolenski/article/details/7982555
二面: 1、提示詞實現Trie樹+hash 2、最快速度求兩個數組之交集; 3、文章最短摘要生成;
網易有道
1、試着用最小的比較次數去尋找數組中的最大值和最小值。 解法一: 掃描一次數組找出最大值;再掃描一次數組找出最小值。 比較次數2N-2
解法二: 將數組中相鄰的兩個數分在一組, 每次比較兩個相鄰的數,將較大值交換至這兩個數的左邊,較小值放於右邊。 對大者組掃描一次找出最大值,對小者組掃描一次找出最小值。 比較1.5N-2次,但需要改變數組結構 解法三: 每次比較相鄰兩個數,較大者與MAX比較,較小者與MIN比較,找出最大值和最小值。
迅雷面試題
1、寫一個字符串插入的函數 2、問了我關於虛函數底層的實現 http://blog.csdn.net/hackbuteer1/article/details/7883531 3、寫了快排、堆排 http://blog.csdn.net/hackbuteer1/article/details/6568913 4、問我TCP、UDP的一些知識 http://blog.csdn.net/hackbuteer1/article/details/6845406 5、還問了我一些Linux的知識 6、讓我實現紅黑樹的刪除操作 http://blog.csdn.net/hackbuteer1/article/details/7760584
網新恆天一面
1、考察指針int (*p)[10]和int *p[10]的區別,用法
2、sizeof(),strlen()的區別和用法
2.1、sizeof()是操作符,strlen()是函數;
2.2、sizeof后面跟的是類型或者函數名,strlen的參數只能是char*;
2.3、sizeof返回的是字節大小,strlen返回的是字符個數。
3、堆、棧的區別和用法
3.1、
棧(stack):由編譯器自動分配釋放,存放函數的參數和局部變量的值。其操作方式類似於數據結構中的棧(先進后出)
堆(heap):一般用程序員通過malloc自動分配,也必須由程序員free釋放所占用的內存。
3.2
棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思
是棧頂的地址和棧的最大容量是系統預先規定好的,在 WINDOWS下,棧的大小是2M(也有的
說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩余空間時,將提示
overflow。因此,能從棧獲得的空間較小。
堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲的
空閑內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限
於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。
4、多繼承的優點與缺點
多重繼承的優點是對象可以調用多個基類中的接口。
多重繼承的缺點是容易出現繼承向上的二義性。
詳見:http://blog.csdn.net/jandunlab/article/details/14110117
5、(1)IO2:30ms, CPU 20ms, IO1 20ms, CPU 30ms
(2) IO1 20ms, CPU 20ms, IO2 10ms
(3) CPU 30ms, IO1 20ms
求三種情況的CPU和IO占用率
網新恆天二面:
1、內聯函數與宏的區別
1.1、內聯函數在運行時可調試,而宏定義不可以;
1.2、編譯器會對內聯函數的參數類型做安全檢查或自動類型轉換(同普通函數),而宏定義則不會;
1.3、內聯函數可以訪問類的成員變量,宏定義則不能;
詳情:http://blog.csdn.net/gao675597253/article/details/7397373
2、與信號量相關知識的考察,具體題目記不清了,反正知道基本概念就會做
詳見:http://blog.csdn.net/sunlovefly2012/article/details/9396201
3、填空,考察頁式虛擬內存的缺頁情況,也是知道這部分知識點就會做的題
即頁面替換算法。
1、理想頁面置換算法(OPT):這是一種理想的頁面替換算法,在實際中不可能實現。該算法的思想是:發生缺頁時,選擇以后永不使用或在最長時間內不再被訪問的內存頁面予以淘汰。
2、先進先出頁面置換算法(FIFO):選擇最先進入內存的頁面予以淘汰。
3、最近最久未使用算法(LRU):選擇在最近一段時間內最久沒有使用過的頁,把它淘汰。
4、最少使用算法(LFU):選擇到當前時間為止被訪問次數最少的頁轉換。
4、類的繼承相關知識點的考察,是一道程序輸出分析題
5、棧的類的成員函數的實現,程序填空題。
6、模板函數與函數模板的區別
7、函數模板與類模板的區別
百度筆試題
1、數組,鏈表的優缺點:這個問題比較簡單不過我自己經常會忽略的一點是數組是固定空間,鏈表是可變空間
數組和鏈表都是線性表,但數組是一組元素有序地存儲在連續的內存單元中,而鏈表的節點元素存儲的內存單元並不是連續的。
由於存儲性質,導致數組的查找可根據下標直接定位,而鏈表的查找需要遍歷,因此查找的效率數組比鏈表要高,而插入和刪除一個元素,數組需要平均移動二分之一的元素,而鏈表可以直接通過斷鏈和指針實現插入和刪除。
對於樹的操作一般用到鏈表,對於圖的操作一般用到數組。
數組應用場景:
1、注重存儲密度;
2、經常做的運算是按序號訪問數據元素;
3、數組更容易實現,任何高級語言都支持;
4、構建的線性表較穩定。
鏈表應用場景:
1、對線性表的長度或者規模難以估計;
2、頻繁做插入刪除操作;
3、構建動態性比較強的線性表。
2、a[N][20]輸入N個長度不超過20的字符串,比較這些字符串中是否有完全相同的字母,且相同字母數是否相等。如何改進該算法,降低復雜度。
3、黑:A Q 4
紅:J 8 4 2 7 3
梅:K Q 5 4 6
方:A 5
有以上16張撲克牌老板從中選擇了一張,之后把這張牌的點數告訴了員工甲,把花色告訴了員工乙。之后按以上方式將16張牌平攤在桌面上。
————甲說:我不知道這張牌是什么。
————乙說:我知道你不知道。
————甲說:我現在知道了。
————乙說:我也知道了。
這張牌是什么?
應該是方5.
3.1、從甲的第一句話可以分析,這張牌不是J、8、2、7、3、K、6。
3.2、從乙的第一句話可以分析,這張牌不是紅或者梅。
3.3、從甲的第二句話可以分析,這張牌不是A。其實甲在說謊,他還不確定是黑Q、4還是方5。
3.4、從乙的第二句話可以分析,這張牌就是方5,因為黑中有兩個Q和4,而方只有一個5。
4、A:M*M矩陣,求字符串S是否存在A的連續對角線上。(這題應該有涉及到一個之字二維矩陣方面的知識) A若為內存裝不下的大矩陣該如何處理?
5、系統接收數據包32字節,第1字節為優先級,其余為數據。設計一個調度算法 (1)優先級高的先處理 (2)同等條件下,請求次數多的先處理 (3)優先級高的一定比優先級低的先處理 寫出所用的數據結構的定義,計算空間容量。
阿里巴巴B2B一面
1、各種排序算法的比較次數
2、static、auto未初始化的初始值 http://blog.csdn.net/hackbuteer1/article/details/7487694
3、x*=y+8,給出x,y的值,求該表達式計算后二者的值
x=1,y=2,x*=y+8后,y=2,x=10。
4、enum類型的default賦值規則
enum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
枚舉量Monday、Tuesday等的值默認分別為0-6,我們可以顯式的設置枚舉量的值:
enum enumType {Monday=1, Tuesday=2, Wednesday=3, Thursday=4, Friday=5, Saturday=6, Sunday=7};
指定的值必須是整數!
詳情:http://jingyan.baidu.com/article/e75aca85526c1b142edac6d9.html
5、定義函數F(int x){return (x*x);} 求F(3+5)
F(3+5)=64
6、fgets(s,n,f)函數的功能
原型是char *fgets(char *s, int n, FILE *stream);
從流中讀取n-1個字符,除非讀完一行,參數s是來接收字符串,如果成功則返回s的指針,否則返回NULL。
形參注釋:*string結果數據的首地址;n-1:一次讀入數據塊的長度,其默認值為1k,即1024;stream文件指針
說得簡單一點就是從f這個文件輸入流中讀取n-1個字符,存到s中。
如果一行的字符數小於n-1,那么就是一行的字符數,所以應該理解為不超過n-1,如果一行的長度大於n-1,就是n-1個字符
7、定義*s="ab\0cdef",輸出該字符可以看到什么結果
ab。因為priintf函數以\0為字符串結束標記。
8、還是static相關知識——在此說明一下static這個關鍵字相當重要,在筆試中出現率為100%,在面試中出現率為50%。
http://blog.csdn.net/hackbuteer1/article/details/7487694
JAVA中的static 修飾符
1、static變量
按照是否靜態的對類成員變量進行分類可分兩種:一種是被static修飾的變量,叫靜態變量或類變量;另一種是沒有被static修飾的變量,叫實例變量。
兩者的區別是:
對於靜態變量在內存中只有一個拷貝(節省內存),JVM只為靜態分配一次內存,在加載類的過程中完成靜態變量的內存分配,可用類名直接訪問(方便),當然也可以通過對象來訪問(但是這是不推薦的)。
對於實例變量,沒創建一個實例,就會為實例變量分配一次內存,實例變量可以在內存中有多個拷貝,互不影響(靈活)。
所以一般在需要實現以下兩個功能時使用靜態變量:
在對象之間共享值時
方便訪問變量時
2、靜態方法
靜態方法可以直接通過類名調用,任何的實例也都可以調用,
因此靜態方法中不能用this和super關鍵字,不能直接訪問所屬類的實例變量和實例方法(就是不帶static的成員變量和成員成員方法),只能訪問所屬類的靜態成員變量和成員方法。
因為實例成員與特定的對象關聯!這個需要去理解,想明白其中的道理,不是記憶!!!
因為static方法獨立於任何實例,因此static方法必須被實現,而不能是抽象的abstract。
例如為了方便方法的調用,Java API中的Math類中所有的方法都是靜態的,而一般類內部的static方法也是方便其它類對該方法的調用。
靜態方法是類內部的一類特殊方法,只有在需要時才將對應的方法聲明成靜態的,一個類內部的方法一般都是非靜態的
3、static代碼塊
static代碼塊也叫靜態代碼塊,是在類中獨立於類成員的static語句塊,可以有多個,位置可以隨便放,它不在任何的方法體內,JVM加載類時會執行這些靜態的代碼塊,如果static代碼塊有多個,JVM將按照它們在類中出現的先后順序依次執行它們,每個代碼塊只會被執行一次。例如:
public class Test5 {
private static int a;
private int b;
static{
Test5.a=3;
System.out.println(a);
Test5 t=new Test5();
t.f();
t.b=1000;
System.out.println(t.b);
}
static{
Test5.a=4;
System.out.println(a);
}
public static void main(String[] args) {
// TODO 自動生成方法存根
}
static{
Test5.a=5;
System.out.println(a);
}
public void f(){
System.out.println("hhahhahah");
}
}
運行結果:
3
hhahhahah
1000
4
5
利用靜態代碼塊可以對一些static變量進行賦值,最后再看一眼這些例子,都一個static的main方法,這樣JVM在運行main方法的時候可以直接調用而不用創建實例。
9、數據庫中索引,簇索引,非簇,唯一,復合,覆蓋索引的區別
詳解:http://sunct.iteye.com/blog/1933511
圖文理解:http://www.jb51.net/article/29693.htm
補充視圖的相關概念:http://www.cnblogs.com/GISDEV/archive/2008/02/13/1067817.html
10、SQL語句和范式是對數據庫有要求的公司筆試必考點之一
SQL語句:sql內連接和外連接。內連接就是表結果集的交集,而外連接是表結果集的並集。
補充:JVM類加載機制-http://blog.csdn.net/a19881029/article/details/17068191
阿里巴巴B2B二面
1、通配符的含義
通配符是一種特殊語句,主要有星號(*)和問號(?),用來模糊搜索文件。
2、死鎖的基本知識——死鎖是各大筆試面試中出現率50%的知識點
產生死鎖的原因主要是:
(1) 因為系統資源不足。
(2) 進程運行推進的順序不合適。
(3) 資源分配不當等。
如果系統資源充足,進程的資源請求都能夠得到滿足,死鎖出現的可能性就很低,否則
就會因爭奪有限的資源而陷入死鎖。其次,進程運行推進順序與速度不同,也可能產生死鎖。
產生死鎖的四個必要條件:
(1) 互斥條件:一個資源每次只能被一個進程使用。
(2) 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
(3) 不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。
(4) 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。
這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之
一不滿足,就不會發生死鎖。
死鎖的解除與預防:
理解了死鎖的原因,尤其是產生死鎖的四個必要條件,就可以最大可能地避免、預防和
解除死鎖。所以,在系統設計、進程調度等方面注意如何不讓這四個必要條件成立,如何確
定資源的合理分配算法,避免進程永久占據系統資源。此外,也要防止進程在處於等待狀態
的情況下占用資源。因此,對資源的分配要給予合理的規划。
3、信號量P、V原語的相關知識點
詳見:http://blog.csdn.net/sunlovefly2012/article/details/9396201
4、有向圖的鄰接表表示
//有向圖的鄰接表表示法 #include <stdio.h> #include <malloc.h> #define MAX_VERTEX_NUM 50//定義圖的最大頂點數 typedef char VertexData; typedef struct EdgeNode//邊表結點 { int adjvex;//鄰接點域 VertexData data; struct EdgeNode *next;//邊結點所對應的下一個邊結點 }EdgeNode; typedef struct VertexNode//定點表結點 { VertexData data; EdgeNode *firstedge;//頭結點所對應的第一個邊結點 }VertexNode; typedef struct AdjList { int VexNum,ArcNum;//定義圖的頂點數和邊數 VertexNode vertex[MAX_VERTEX_NUM];//定義頭結點數組 }AdjList; void CreateGraph(AdjList *adj) { int e,s,d,n,i; char c; EdgeNode *q = NULL; printf("輸入頂點數\n"); scanf("%d",&n); printf("輸入邊數\n"); scanf("%d",&e); adj->VexNum=n; adj->ArcNum = e; //初始化表頭結點 for(i=1;i<=n;i++){ printf("輸入第%d個頂點的頂點名稱:\n",i); //輸入流中還有殘留的字符,getchar()會接受那個字符。可以在調用getchar()之前用fflush(stdin)刷新一下輸入緩沖區。 fflush(stdin); c = getchar(); adj->vertex[i].data=c;//頂點名稱,是一個字符 adj->vertex[i].firstedge = NULL; } for(i=1;i<=e;i++){ printf("輸入第%d條邊的起點和終點:\n",i); scanf("%d %d",&s,&d);//輸入邊的起始和終止 q=(EdgeNode *)malloc(sizeof(EdgeNode));//創建一個表結點 if(q==NULL) return; q->adjvex=d; q->next = adj->vertex[s].firstedge;//新加入的結點都是頭結點之后, //原來在頭結點之后的結點要后移 adj->vertex[s].firstedge = q; } } void DisplayGraph(AdjList *adj) { int n=adj->VexNum;//頂點個數,后面要遍歷每一個點點 EdgeNode *q=NULL; int i; for(i=1;i<=n;i++) { q=adj->vertex[i].firstedge; if(q!=NULL) { printf("從結點%c出發的邊有:",adj->vertex[i].data); while(q!=NULL) { printf("%c->%c",adj->vertex[i].data,adj->vertex[q->adjvex].data); q=q->next; } } } } void main() { AdjList *adj=(AdjList *)malloc(sizeof(AdjList)); CreateGraph(adj); DisplayGraph(adj); }
5、STL中迭代器的工作原理,迭代器與普通指針有什么區別?
迭代器和指針相同的地方: 1、指針和iterator都支持與整數進行+,-運算,而且其含義都是從當前位置向前或者向后移動n個位置 2、指針和iterator都支持減法運算,指針-指針得到的是兩個指針之間的距離,迭代器-迭代器得到的是兩個迭代器之間的距離 3、通過指針或者iterator都能夠修改其指向的元素 通過上面這幾點看,兩者真的很像,但是兩者也有着下面的幾個不同地方 1、out操作符可以直接輸出指針的值,但是對迭代器進行在操作的時候會報錯。通過看報錯信息和頭文件知道,迭代器返回的是對象引用而不是對象的值,所以cout只能輸出迭代器使用*取值后的值而不能直接輸出其自身。 2、指針能指向函數而迭代器不行,迭代器只能指向容器 這就說明了迭代器和指針其實是完全不一樣的概念來的。指針是一種特殊的變量,它專門用來存放另一變量的地址,而迭代器只是參考了指針的特性進行設計的一種STL接口。 筆者曾在網上看到這樣一種說法:迭代器是廣義指針,而指針滿足所有迭代器要求。迭代器是STL算法的接口,而指針是迭代器,因此STL算法可以使用指針來對基於指針的非STL容器進行操作。 筆者覺得上面說法也有幾分道理,但是到底正不正確就留給看官自己判斷了。但是有一點希望大家注意的是:千萬不要把指針和迭代器搞混了。也許某些編譯器使用指針來實現迭代器以至於有些人會誤以為指針和迭代器是一個概念來的。
6、什么是友元? 7、delete、new的用法 8、typename的用法
9、編程判斷一個數是否為2的冪
思路:2,4,8,16,32....都是2的n次冪
轉換為二進制分別為:
10 100 1000 10000 100000
這些數減1后與自身進行按位與,如果結果為0,表示這個數是2的n次冪
01 011 0111 01111 011111
10&01 = 0 100&011 = 0 1000&0111 = 0 10000&01111 = 0 100000&011111 = 0
#include <stdio.h> /* 判斷一個整數是否為2的次方冪 */ bool fun(int v) { bool flag = 0; if((v>0)&&(v&(v-1))==0) flag = 1; return flag; } int main(void) { int a; printf("請輸入1個32位的整數:"); scanf("%d",&a); if(fun(a)) printf("這個數是2次方冪\n"); else printf("這個數不是2次方冪\n"); return 0; }
10、你怎樣重新改進和設計一個ATM銀行自動取款機?
10.1、用指紋識別、人臉識別來替代密碼輸入;
10.2、語音交互來代替傳統按鍵式的人機交互方式。
12、10000Mbps萬兆交換機怎么實現?
13、操作符重載的相關知識點,大題,具體記不清了
人民搜索的筆試題
1、打印漢諾塔移動步驟,並且計算復雜度
2、計算兩個字符串的是否相似(字符的種類,和出現次數相同)
編程之美中的一道經典的動態規划題目——計算兩個字符串的相似度
public class StringSimilar {
public int fun(String source,String target){
int i,j;
int[][] d = new int[source.length()+1][target.length()+1];
for(i=1;i<source.length()+1;i++){/*初始化臨界值*/
d[i][0]=i;
}
for(j=1;j<target.length()+1;j++){/*初始化臨界值*/
d[0][j]=j;
}
for(i=1;i<source.length()+1;i++){/*動態規划填表*/
for(j=1;j<target.length()+1;j++){
if(source.substring(i-1, i).equals(target.substring(j-1, j))){
d[i][j]=d[i-1][j-1];/*source的第i個和target的第j個相同時*/
}else{/*不同的時候則取三種操作最小的一個*/
d[i][j]=min(d[i][j-1]+1,d[i-1][j]+1,d[i-1][j-1]+1);
}
}
}
return d[source.length()][target.length()];
}
private int min(int i, int j, int k) {
int min = i<j?i:j;
min = min<k?min:k;
return min;
}
public static void main(String[] args) {
StringSimilar ss = new StringSimilar();
System.out.println(ss.fun("SNOWY", "SUNNY"));//3
System.out.println(ss.fun("a", "b"));//1
System.out.println(ss.fun("abdd", "aebdd"));//1
System.out.println(ss.fun("travelling", "traveling"));//1
}
}
3、定義二叉樹,節點值為int,計算二叉樹中的值在[a,b]區間的節點的個數
4、動態規划題:一條路有k可坑,每次能跳平方數步長(1 4 9 16。。),不能跳到坑里,從a跳到b最少幾步?
5、給一個整數數組,求數組中重復出現次數大於數組總個數一半的數。
1、對以孩子兄弟鏈接的樹進行遍歷,不能用遞歸,也不能借助任何輔助空間
2、假設數組B是升序Int數組A循環移若干得到的位,實現對數組B進行查找的高效算法
step1:從數組的末尾向前遍歷,比較B[i]<B[i-1],如果是,則B[i]就是A[0],記錄下標j=i;
step2:判讀查找數據data,data>B[0],則在B[0]~B[j-1]范圍內通過二分查找查找該data;如果data<B[i],則在B[j]~B[B.length-1]范圍內通過二分查找查找該data;
step3:輸出該data在數組B中的下標
時間復雜度:假設數組長度為n,查找下標j的時間復雜度為O(n),查找data的時間復雜為:O(log2(n)),總的時間復雜度為O(n+log2(n))=O(n)。
3、只有整數和+-*/四種運算組成的算術表達書,實現其求值
考察的是后綴表達式,運用到棧的知識點。
package stack; public class MyStack { private int maxSize; private int[] stackArray; private int top; public MyStack(int s) { maxSize = s; stackArray = new int[maxSize]; top = -1; } public void push(int c) { stackArray[++top] = c; } public int pop() { return stackArray[top--]; } public int peek() { return stackArray[top]; } public boolean isEmpty() { return (top == -1); } public boolean isFull() { return (top == maxSize - 1); } public static void main(String[] args) { MyStack theStack = new MyStack(10); // theStack.push(10); // theStack.push(20); // theStack.push(30); // theStack.push(40); // theStack.push(50); while (!theStack.isEmpty()) { long value = theStack.pop(); System.out.print(value); System.out.print(" "); } System.out.println(""); } }
package peopleseach; import java.util.Scanner; import stack.MyStack; /** * 后綴表達式 * * @author he * */ public class SuffixExpression { /** * 輸入后綴表達式 * * @param expression * 后綴表達式 */ private static String InputExpression(MyStack stack) { Scanner scanner = new Scanner(System.in); String signStr="";//符號字符串 String str = null; do { System.out.println("請輸入整數或者計算符----輸入q即為退出"); str = scanner.nextLine(); if (!str.isEmpty() && !"q".equals(str)) { char c = str.charAt(0); //如果是計算符號,則拼接成符號字符串 if(c=='+'||c=='-'||c=='*'||c=='/') signStr+=c; else //如果是整數,則入棧 stack.push(Integer.parseInt(str)); } } while (!"q".equals(str)); return signStr; } /** * 計算后綴表達式 * * @param signStr * 計算符號字符串 */ private static void calculate(MyStack stack, String signStr) { int result=0; for (int i = 0; i < signStr.length(); i++) { char c = signStr.charAt(i); int b = stack.pop(); int a = stack.pop(); switch (c) { case '+': result = a + b; break; case '-': result = a - b; break; case '*': result = a * b; break; case '/': result = a / b; break; } stack.push(result); } System.out.println("計算結果為:"+result); } /** * @param args */ public static void main(String[] args) { MyStack stack = new MyStack(10); String signStr = InputExpression(stack); calculate(stack, signStr); } }
4、還有一個是考貪心算法的,你讓他們看算法導論那本書,關於fractional knapsack problem的那一段,就是0-1背包的一種變形;
5、鏈表相鄰元素翻轉,如a->b->c->d->e->f-g,翻轉后變為:b->a->d->c->f->e->g
6、求正整數n所有可能的和式的組合(如;4=1+1+1+1、1+1+2、1+3、2+1+1、2+2)
1、實現一個atoi函數==>'注意正負號的判定'
/* * name:xif * coder:xifan@2010@yahoo.cn * time:08.20.2012 * file_name:my_atoi.c * function:int my_atoi(char* pstr) */ int my_atoi(char* pstr) { int Ret_Integer = 0; int Integer_sign = 1; /* * 判斷指針是否為空 */ if(pstr == NULL) { printf("Pointer is NULL\n"); return 0; } /* * 跳過前面的空格字符 */ while(isspace(*pstr) == 0) { pstr++; } /* * 判斷正負號 * 如果是正號,指針指向下一個字符 * 如果是符號,把符號標記為Integer_sign置-1,然后再把指針指向下一個字符 */ if(*pstr == '-') { Integer_sign = -1; } if(*pstr == '-' || *pstr == '+') { pstr++; } /* * 把數字字符串逐個轉換成整數,並把最后轉換好的整數賦給Ret_Integer */ while(*pstr >= '0' && *pstr <= '9') { Ret_Integer = Ret_Integer * 10 + *pstr - '0'; pstr++; } Ret_Integer = Integer_sign * Ret_Integer; return Ret_Integer; }
2、翻轉一個句子,其中單詞是正序的
算法:
1、將字符串str[0]和str[str.length-1]互換元素,str[1]和str[str.length-2]互換元素····直到將str翻轉;時間復雜度:O(n/2)
2、再將單詞翻轉。時間復雜度:O(nlog2(n))
package peopleseach; /** * 翻轉一個句子,其中單詞是正序的 * * @author he * */ public class OverturnSentence { private static String overturn(String ss) { char[] sentence = ss.toCharArray(); //將字符串str[0]和str[str.length-1]互換元素,str[1]和str[str.length-2]互換元素····直到將str翻轉;時間復雜度:O(n/2) for(int i=0;i<sentence.length/2;i++){ char temp = sentence[i]; sentence[i] = sentence[sentence.length-1-i]; sentence[sentence.length-1-i] = temp; } System.out.println(new String(sentence)); int start = 0; for(int i=0;i<sentence.length;i++){ if(!((sentence[i] >= 'a'&&sentence[i]<='z') ||(sentence[i] >= 'A'&&sentence[i]<='Z'))){ //如果不是英文字符,說明一個字符完結,即str[start]-str[i-1]組成一個單詞。接着就對該單詞翻轉 for(int j=0;j<(i-start)/2;j++){ char temp = sentence[start+j]; sentence[start+j] = sentence[i-1-j]; sentence[i-1-j] = temp; } start = i+1; } } return new String(sentence); } /** * @param args */ public static void main(String[] args) { System.out.println(overturn("I am a good boy!")); } }
3、二叉樹兩個結點中的最小公共子結點==>求長度,長度之差,遠的先走,再一起走
4、三角陣中從第一行到最后一行(給出搜索方向的限制)找一個連續的最大和。
package peopleseach; /** * @author he * 題目:輸入一個整形數組,數組里有正數也有負數。數組中連續的一個或多個整數組成一個子數組,每個子數組都有一個和。 * 求所有子數組的和的最大值。要求時間復雜度為O(n)。 浙大數據結構課本上有 思路: * 求連續數字之和,當和為負值,拋棄.當和為正值,比較其與最大值,如大於,則替換之 */ public class ContinuationMax { /** * 連續的最大和 * @param array 上三角矩陣的壓縮存儲數組 */ public static void findMax(int[] array) { int curMax = 0,max = 0; for(int i=0;i<array.length;i++){ curMax += array[i]; if(curMax < 0) curMax = 0; else if(curMax > max) max = curMax; } //if all data is negative if(max == 0){ max = array[0]; //find the max negative for(int i=1;i<array.length;i++) if(array[i]>max) max = array[i]; } System.out.println("The ContinuationMax is "+max); } /** * @param args */ public static void main(String[] args) { int[][] tarray = new int[][]{ {1, -2, 3, 10},{Integer.MAX_VALUE,-2, -3, 5},{Integer.MAX_VALUE,Integer.MAX_VALUE,6,-7},{Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,11}}; int n=(1+tarray.length)*tarray.length/2; int[] array = new int[n]; int m = 0; for(int i=0;i<tarray.length;i++) for(int j=i;j<tarray.length;j++){ array[m++] = tarray[i][j]; System.out.println(tarray[i][j]); } findMax(array); } }
5、實現一個STL中的vector中的盡量多的方法。
6、字符串移動(字符串為*號和26個字母的任意組合,把*號都移動到最左側,把字母移到最右側並保持相對順序不變),要求時間和空間復雜度最小。
/** ** author :hackbuteer ** 時間復雜度 :O(n);空間復雜度:O(1)
** 注意:從str數組末尾向前遍歷要優於從前向后遍歷 **/ void Arrange(char *str , int n) { int i , k = n-1; for(i = n - 1 ; i >= 0 ; --i) { if(str[i] != '*') { if(str[k] == '*') { str[k] = str[i]; str[i] = '*'; } --k; } } }
7、說說outer join、inner join、left join、right join的區別是什么?
SQL語句:sql內連接和外連接。(inner join)內連接就是表結果集的交集,外連接(outer join)是表結果集的並集。 外連接又分為左連接(left join)和右連接(right join)。
