1. 程式人生 > >騰訊面試題:快速找到未知長度單鏈表的中間結點

騰訊面試題:快速找到未知長度單鏈表的中間結點

題目:快速找到未知長度單鏈表的中間結點

首先分析一下,既然是一個面試題,就一定有普通方法和高階方法,而高階方法無疑會為你大大加分!

普通方法很簡單:首先遍歷一遍單鏈表以確定單鏈表的長度L。然後再此從頭結點出發迴圈L/2次找到單鏈表的中間結點。

普通方法的演算法複雜度為:O(L+L/2) = O(3L/2)

普通方法的實現程式碼:

    #include<stdio.h>
    #include<malloc.h>
    #include<time.h>
    #include<stdlib.h>
    #include<math.h>

	struct node
        {
             int data;     //elementype表示一種資料型別,可能是int/char等等
             struct node *next;   //next 指標,用於連結串列結構指向下一個節點
        };

	typedef struct node node; //重定義struct node型別為node

    int GetMidNode(node* L);  //函式宣告
    void List(node* head);
    node* Creat(int Count);
    int Length(node *L);

	int main()
        {
        node* head;
        int a;
        int Num;

		printf("1.Creat linklist\n2.View linklist\n3.Length of linklist\n4.Value of middle node\n0.Exit\n");
        while(1)
        {
			scanf("%d",&a);
			switch(a)
				{

				case 1:
					printf("Enter the number of linked list nodes:\n");
					scanf("%d",&Num);
					head = Creat(Num);
					printf("\n");
					break;
				case 2:
					printf("List:\n");
					List(head);
					printf("\n");
					printf("\n");
					break;
				case 3:
					printf("Length of linklist:\n");
					printf("%d",Length(head));
					printf("\n");
					printf("\n");
					break;
				case 4:
					printf("Value of middle node:\n");
					printf("%d",GetMidNode(head));
					printf("\n");
					printf("\n");
					break;
				case 0:
					return 0;
				}

		}
        return 0;
		}


    node* Creat(int Count)  //建立連結串列
    {
        node *p1,*p2,*head;
        int n;
        srand(time(NULL));//生成種子
        head = p1 = (node*)malloc(sizeof(node));
		head->data = rand()%1000;
        head->next = NULL;
        for (n = 1;n < Count;n++)
            {
                p2 = (node*)malloc(sizeof(node));
                p2->data = rand()%1000;
                p1->next = p2;
                p1 = p2;
            }
        p1->next = NULL;
        return(head);
    }


	void List(node* head)  //列印連結串列
        {
            node *p1;
            p1 = head;
            while(p1!= NULL)
            {
                printf("%4d",p1->data);
                p1 = p1->next;
            }
        }


	int GetMidNode(node* L)  //尋找連結串列中間值
        {
            int a,i,n;
            n = Length(L);  //獲取連結串列長度
			for (i = 1;i < (n+1)/2;i++)
			{
				L = L->next;  //從頭查詢連結串列,到連結串列一半
			}
			a = L->data;
			return a;
        }


	int Length(node *L)  //計算連結串列長度
        {
			int n = 0;
			while(L->next!= NULL)
			{
				n++;
				L = L->next;
			}
			n++;
			return n;
		}

這段程式碼實現了4個功能:1. 建立連結串列 2. 檢視連結串列 3. 計算連結串列長度 4. 查詢連結串列中間值

在第四個功能中我們使用了普通的方法,也就是 int GetMidNode(node* L) 函式


=================================================

高階方法利用快慢指標原理:設定兩個指標*search和*mid都指向單鏈表的頭結點。其中*search的移動速度是*mid的2倍。當*search指向末尾結點的時候,*mid正好在中間了。也就是一種標尺的思想。

高階方法的演算法複雜度為:O(L/2)

高階方法實現程式碼:

    #include<stdio.h>
    #include<malloc.h>
    #include<time.h>
    #include<stdlib.h>
    #include<math.h>

	struct node
        {
             int data;     //elementype表示一種資料型別,可能是int/char等等
             struct node *next;   //next 指標,用於連結串列結構指向下一個節點
        };

	typedef struct node node; //重定義struct node型別為node

    int GetMidNode(node* L);  //函式宣告
    void List(node* head);
    node* Creat(int Count);
    int Length(node *L);

	int main()
        {
        node* head;
        int a;
        int Num;

		printf("1.Creat linklist\n2.View linklist\n3.Length of linklist\n4.Value of middle node\n0.Exit\n");
        while(1)
        {
			scanf("%d",&a);
			switch(a)
				{

				case 1:
					printf("Enter the number of linked list nodes:\n");
					scanf("%d",&Num);
					head = Creat(Num);
					printf("\n");
					break;
				case 2:
					printf("List:\n");
					List(head);
					printf("\n");
					printf("\n");
					break;
				case 3:
					printf("Length of linklist:\n");
					printf("%d",Length(head));
					printf("\n");
					printf("\n");
					break;
				case 4:
					printf("Value of middle node:\n");
					printf("%d",GetMidNode(head));
					printf("\n");
					printf("\n");
					break;
				case 0:
					return 0;
				}

		}
        return 0;
		}


    node* Creat(int Count)  //建立連結串列
    {
        node *p1,*p2,*head;
        int n;
        srand(time(NULL));//生成種子
        head = p1 = (node*)malloc(sizeof(node));
		head->data = rand()%1000;
        head->next = NULL;
        for (n = 1;n < Count;n++)
            {
                p2 = (node*)malloc(sizeof(node));
                p2->data = rand()%1000;
                p1->next = p2;
                p1 = p2;
            }
        p1->next = NULL;
        return(head);
    }


	void List(node* head)  //列印連結串列
        {
            node *p1;
            p1 = head;
            while(p1!= NULL)
            {
                printf("%4d",p1->data);
                p1 = p1->next;
            }
        }


	int GetMidNode(node* L)  //尋找連結串列中間值
        {
            int a;
            node *search,*mid;
            mid = search = L;
            while(search->next != NULL)
            {
                if(search->next->next != NULL)
					{
						search = search->next->next;
						mid= mid->next;
					}
                else
					{
						search = search->next;
					}
            }
            a = mid->data;
            return a;
        }


	int Length(node *L)  //計算連結串列長度
        {
			int n = 0;
			while(L->next!= NULL)
			{
				n++;
				L = L->next;
			}
			n++;
			return n;
		}

與之前程式碼的不同點在於int GetMidNode(node* L) 函式的實現,用到了快慢指標的原理。當快指標遍歷了連結串列的時候慢指標正好到達連結串列的一半位置。

結果展示:

  

相關推薦

試題快速找到未知長度單鏈中間結點

題目:快速找到未知長度單鏈表的中間結點首先分析一下,既然是一個面試題,就一定有普通方法和高階方法,而高階方法無疑會為你大大加分!普通方法很簡單:首先遍歷一遍單鏈表以確定單鏈表的長度L。然後再此從頭結點出發迴圈L/2次找到單鏈表的中間結點。普通方法的演算法複雜度為:O(L+L/

程式設計師試題快速出一個數組中的兩個數字,讓這兩個數字之和等於一個給定的值

能否快速找出一個數組中的兩個數字,讓這兩個數字之和等於一個給定的值,為了簡化起見,我們假設這個陣列中肯定存在至少一組符合要求的解。 假如有如下的兩個陣列,如圖所示: 5,6,1,4,7,9,8 給定Sum= 10 1,5,6,7,8,9 給定Sum=

試題根據上排給出的十個數,在其下排填出對應的十個數。

問題描述:根據上排給出的十個數,在其下排填出對應的十個數,要求下排每個數都是先前上排那十個數在下排出現的次數。 上排的十個數如下: 0,1,2,3,4,5,6,7,8,9 答案是: 6,2,1,0,0,0,1,0,0,0 我在這裡使用DFS,並且使用兩個函式互相遞迴。 程

試題模板實現一個棧,要求Push(入棧),Pop(出棧),Max(返回最大值的操作)的時間複雜度為O(1)

解題思路:要用模板實現亂序入棧的陣列每次pop()出棧都能得到當前棧中Max的最大值,就必須在push()入棧時進行維護操作,使的每次入棧的元素都能夠找到合適的位置並push(),每次push()操作完成後棧中的元素都能夠按從棧頂到棧底從大到小排列即可。這就需要寫一個不同於常

快速找到未知長度單鏈中間節點

變量 div ride span 一個 ima list 方法 .com 在討論之前,我們首先首先要明白,什麽是單鏈表? 單鏈表:鏈接方式存儲的線性表 單鏈表的結點結構 ┌──┬──┐ │data│next│ └──┴──┘  data域--存放結點值的數

試題 快慢指標演算法快速找到單鏈中間

快速找到未知長度的單鏈表的中間節點 普通方法就是遍歷兩次,第一次遍歷得到連結串列長度,第二次遍歷得到中間值。時間複雜度為1.5n。(這裡需要強調1.5) 快速連結串列方法就是利用兩個指標,慢指標每次移動一個數據,快指標每次移動兩個資料。最外層的迴圈用快指標。當快

【原理思路】大資料中中位數(試題

題目: 在一個大檔案中有100億個32位整數,亂序排列,要求找出中位數;記憶體限制為512M;請寫出演算法設計思路; 基本分析: (1)中位數的定義:一個給定排序好的序列,奇數個的話,我們就取中間的一個;偶數個的話,我們一般取中間兩個數的平均值;因此對於本題,我們需得到中

[js高手之路]javascript試題學習封裝一個簡易的異步隊列

騰訊 selector host .proto 算法 obj 代碼 ner 試題 這道js的面試題,是這樣的,頁面上有一個按鈕,一個ul,點擊按鈕的時候,每隔1秒鐘向ul的後面追加一個li, 一共追加10個,li的內容從0開始技術( 0, 1, 2, ....9 ),首先我

企業必考試題/oldboy目錄下所有7天以前的以log結尾的文件移動到/tmp下。

企業面試題企業必考面試題:查找/oldboy目錄下所有7天以前的以log結尾的文件移動到/tmp下。 要求:請給出至少三種實現方法,有能力的朋友試試看! 方法一、 [root@centos6 oldboy]# mv $(find . -name "*.log" -size +1M -at

阿裏、網易和試題 C/C++

不同的 三次握手 進程組 HR 是什麽 ret 區分 point 兩個 一、線程、鎖 1、Posix Thread互斥鎖 線程鎖創建 a.靜態創建 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; b.動態創建 pt

試題總結 似乎是面試C 方向的 小巫總結

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

試題——螞蟻爬行(C++版)

#include <iostream> #include <limits> #include "ctime" using namespace std; const double DBL_MAX = numeric_limits<double&

C#試題快速排序法

快速排序法:找到一個基準點key,和left,right,比較,比key小的值放到key的坐邊,比key大的值,放到key的右邊。 採用遞迴方式,重複執行判斷,直到排序完成。 //快速排序法法 //排序找出基準點。        private static int

2.判斷一個二叉樹是否是二叉搜尋樹(試題

1.面試的時候當面試官提出來的時候,我立馬想到的就是基於前序遍歷的遞迴方法。但是這個方法在面試官給說一個測試用例的時候就徹底傻眼了。public class Main { public static boolean isSerchBTree(TreeNode root)

試題猜字遊戲---猜1-100之間一個數字,最少多少次?第一次猜的數是幾?

題目: A、B兩人玩猜字遊戲,遊戲規則如下: A選定一個 [1,100]之間的數字背對B寫在紙上,然後讓B開始猜; 如果B猜的偏小,A會提示B這次猜的偏小; 一旦B某次猜的偏大,A就不再提示,此次之後B猜的偏小A也不會再提示,只回答猜對與否。 請問:B至少要猜()次才能保證

python經典試題工作?這些試題你會了嗎?

輸出結果 classes readline 應用 all 就是 last 如果 合數 ? 前言 什麽?你要去找工作?先別急著找工作,先把下面的python面試題先給看了吧,不然你就只是去面試而不是找工作。話說不打沒準備的仗,下面這些基本的面試題都不會你怎麽可能找到工作呢

試題-----JavaScript中arguments物件解析

在騰訊面試中遇到了這樣問題: js程式碼 function test(x,y){ var x = 10; alert(arguments[0],arguments[1]); } test(); 獲取arguments資料 Array.p

一道試題(使用遞迴、迴圈、陣列實現上臺階方法)

//一道騰訊面試題 //題目:有50個臺階,一次走一步或者兩步,有多少種可能? 分析: 如果有一個臺階,則只有一種可能:1; 如果有兩個臺階,只有兩種可能:11或2; 如果有三個臺階,則有三種

試題04.程序和執行緒的區別?

程序和執行緒的區別? 程序和執行緒的主要差別在於它們是不同的作業系統資源管理方式。程序有獨立的地址空間,一個程序崩潰後,在保護模式下不會對其它程序產生影響,而執行緒只是一個程序中的不同執行路徑。執行緒有自己的堆疊和區域性變數,但執行緒之間沒有單獨的地址空間,一個執行緒死掉就

阿里、網易和試題 C/C++

一、執行緒、鎖 1、Posix Thread互斥鎖 執行緒鎖建立 a.靜態建立 pthread_mutex_tmute