1. 程式人生 > >程式設計師面試金典題解

程式設計師面試金典題解

大部分試題在牛客網上測試通過,部分程式碼參考牛客網討論區。

陣列和字串

  • 1.1 確定字元互異

題目描述 請實現一個演算法,確定一個字串的所有字元是否全都不同。這裡我們要求不允許使用額外的儲存結構。

給定一個string iniString,請返回一個bool值,True代表所有字元全都不同,False代表存在相同的字元。保證字串中的字元為Unicode字元。字串的長度小於等於3000。

測試樣例:
"aeiou"
返回:True
"BarackObama"
返回:False

解法一:雜湊法,有兩點要注意,上述要求給出的是Unicode字元,所以雜湊陣列要開到65535,如果要求的是ASCII字元,雜湊陣列開到256即可,但是如果要求不使用額外的儲存空間,這種解法就不行

import java.util.*;
// 時間複雜度O(n),空間複雜度O(1)
public class Different {
    public boolean checkDifferent(String iniString) {
       // if(iniString.length() > 256) {
       //     return false;
       // }
        boolean[] char_set = new boolean[65536];
        for(int i = 0; i < iniString.length(); i++
) { int val = iniString.charAt(i); if(char_set[val]) { return false; } char_set[val] = true; } return true; } }

解法二:使用位運算


import java.util.*;
 
public class Different {
  public boolean checkDifferent(String str) {
//使用異或,因為讓支援ASCII所以判斷下長度,長度超了,肯定重複 if(str.length()>256)return false; for (int i = 0;i<str.length();i++) { for (int j = i+1;j<str.length();j++) { if ((str.charAt(i)^str.charAt(j))==0) return false; } } return true; } }

解法三:遍歷,讓字串中的每一個字元與其餘字元比較。時間複雜度O(n^2),如果是ASCII字元其實也還能接受,空間複雜度O(1)

解法四:若允許修改字串,可以先對字串裡的字元進行排序,然後線性檢查有無相鄰字元相同的情況。排序要佔去O(nlog(n))時間複雜度,空間複雜度也不低。

  • 1.2 原字串翻轉

題目描述 請實現一個演算法,在不使用額外資料結構和儲存空間的情況下,翻轉一個給定的字串(可以使用單個過程變數)。

給定一個string iniString,請返回一個string,為翻轉後的字串。保證字串的長度小於等於5000。

測試樣例:
"This is nowcoder"
返回:"redocwon si sihT"

解法一:這道題用Java我不知道如何原地翻轉,書上用的是c指標做的

import java.util.*;

public class Reverse {
    public String reverseString(String iniString) {
        // write code here
        char[] res = iniString.toCharArray();
        for(int i = 0; i < res.length >> 1; i++) {
            char temp = res[res.length - 1 - i];
            res[res.length - 1 - i] = res[i];
            res[i] = temp;
        }
        return new String(res);
    }
}

解法二:二分法遞迴

連結:https://www.nowcoder.com/questionTerminal/2442435405fa432b99b8ec1cb0315902
來源:牛客網

 public static String r1(String s){
        int length = s.length();
        if(length <= 1)
            return s;
        String left = s.substring(0, length/2);
        String right = s.substring(length/2, length);
        return r1(right)+r1(left);
    }

    public static String r2(String s){
        String reverse = "";
        for(int i=s.length()-1; i>=0; i--){
            reverse += s.charAt(i);
        }
        return reverse;
    }

解法三:C語言解法

void reverse(char* str) {
    char* end = str;
    char temp;
    if(str) {
        while(*end) { // 找到字串末尾
            ++end;
        }
        --end;  // 回退一個字元,因為最後一個字元為null
        // 從字串首尾開始交換兩個字元,直到兩個指標相遇。
        while(str < end) {
            temp = *str;
            *str++ = *end;
            *end-- = temp;
        }
    }
}
  • 1.3 確定兩串亂序同構

題目描述 給定兩個字串,請編寫程式,確定其中一個字串的字元重新排列後,能否變成另一個字串。這裡規定大小寫為不同字元,且考慮字串中的空格。

給定一個string stringA和一個string stringB,請返回一個bool,代表兩串是否重新排列後可相同。保證兩串的長度都小於等於5000。

測試樣例:
"This is nowcoder","is This nowcoder"
返回:true
"Here you are","Are you here"
返回:false

解法一:對兩個字串進行排序,然後比較排序後的字串是否相同

import java.util.*;

public class Same {
    public boolean checkSam(String stringA, String stringB) {
        // write code here
        if(stringA.length() != stringB.length()) {
            return false;
        }
        return sort(stringA).equals(sort(stringB));
    }
    public String sort(String s) {
        char[] content = s.toCharArray();
        Arrays.sort(content);
        return new String(content);
    }
}

解法二:比較兩個字串各個字元的數量是否相同

import java.util.*;

public class Same {
    public boolean checkSam(String stringA, String stringB) {
        // write code here
        if(stringA.length() != stringB.length()) {
            return false;
        }
        int[] letters = new int[256];
        char[] array = stringA.toCharArray();
        for(char c : array) {
            letters[c]++;
        }
        for(int i = 0; i < stringB.length(); i++) {
            int c = (int) stringB.charAt(i);
            if(--letters[c] < 0) {
                return false;
            }
        }
        return true;
    }
    
}
  • 1.4 空格替換

題目描述 請編寫一個方法,將字串中的空格全部替換為“%20”。假定該字串有足夠的空間存放新增的字元,並且知道字串的真實長度(小於等於1000),同時保證字串由大小寫的英文字母組成。

給定一個string iniString 為原始的串,以及串的長度 int len, 返回替換後的string。

測試樣例:
"Mr John Smith”,13
返回:"Mr%20John%20Smith"
”Hello  World”,12
返回:”Hello%20%20World”

解法一:

import java.util.*;
 
public class Replacement {
    public String replaceSpace(String iniString, int length) {
        // 如果允許分配額外空間
        if (iniString == null || iniString.length() <= 0)
            return iniString;
         
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            char c = iniString.charAt(i);
            if (c == ' ')
                sb.append("%20");
            else
                sb.append(c);
        }
        return sb.toString();
    }
}

解法二:

import java.util.*;

public class Replacement {
    public String replaceSpace(String iniString, int length) {
        // write code here
        int spaceCount = 0, index, i = 0;
        char[] str = iniString.toCharArray();
        for(i = 0; i < length; i++) {
            if(str[i] == ' ') {
                spaceCount++;
            }
        }
        index = length + spaceCount * 2;
		str[index] = '\0';
		for (i = length - 1; i >= 0; i--) {
			if (str[i] == ' ') {
				str[index - 1] = '0';
				str[index - 2] = '2';
				str[index - 3] = '%';
				index = index - 3;
			} else {
				str[index - 1] = str[i];
				index--;
			}
		}
        return String.valueOf(str);
    }
}
  • 1.5 基本字串壓縮

題目描述 利用字元重複出現的次數,編寫一個方法,實現基本的字串壓縮功能。比如,字串“aabcccccaaa”經壓縮會變成“a2b1c5a3”。若壓縮後的字串沒有變短,則返回原先的字串。

給定一個string iniString為待壓縮的串(長度小於等於10000),保證串內字元均由大小寫英文字母組成,返回一個string,為所求的壓縮後或未變化的串。

測試樣例
"aabcccccaaa"
返回:"a2b1c5a3"
"welcometonowcoderrrrr"
返回:"welcometonowcoderrrrr"

解法一:

import java.util.*;

public class Zipper {
    public String zipString(String iniString) {
        // write code here
        String mystr = "";
        char last = iniString.charAt(0);
        int count = 1;
        boolean isSame = false;
        for(int i = 1; i < iniString.length(); i++) {
            if(iniString.charAt(i) == last) {
                count++;
                isSame = true;
            } else {
                mystr += last + "" + count;
                last = iniString.charAt(i);
                count = 1;
            }
        }
        if(isSame){
        return mystr + last + count;
        } else {
            return iniString;
        }
        }
}

解法二:使用StringBuffer優化效能

public static String compressBetter(String str) {
		int size = countCompression(str);
		if (size >= str.length()) {
			return str;
		}
		StringBuffer mystr = new StringBuffer();
		char last = str.charAt(0);
		int count = 1;
		for (int i = 1; i < str.length(); i++) {
			if (str.charAt(i) == last) {
				count++;
			} else {
				mystr.append(last);
				mystr.append(count);
				last = str.charAt(i);
				count = 1;
			}
		}
		mystr.append(last);
		mystr.append(count);
		return mystr.toString();
	}
  public static int countCompression(String str) {
		if (str == null || str.isEmpty()) return 0;
		char last = str.charAt(0);
		int size = 0;
		int count = 1;
		for (int i = 1; i < str.length(); i++) {
			if (str.charAt(i) == last) {
				count++;
			} else {
				last = str.charAt(i);
				size += 1 + String.valueOf(count).length();
				count = 1;
			} 
		}
		size += 1 + String.valueOf(count).length();
		return size;
	}
  • 1.6 畫素翻轉

有一副由NxN矩陣表示的影象,這裡每個畫素用一個int表示,請編寫一個演算法,在不佔用額外記憶體空間的情況下(即不使用快取矩陣),將影象順時針旋轉90度。

給定一個NxN的矩陣,和矩陣的階數N,請返回旋轉後的NxN矩陣,保證N小於等於500,影象元素小於等於256。

測試樣例:
[[1,2,3],[4,5,6],[7,8,9]],3
返回:[[7,4,1],[8,5,2],[9,6,3]]

解法:從最外層逐層向裡,按照索引一個一個進行交換,一層一層進行旋轉,

import java.util.*;
// 時間複雜度O(n^2)
public class Transform {
    public int[][] transformImage(int[][] mat, int n) {
        // write code here
        for(int layer = 0; layer < n / 2; layer++) {
            int first = layer;
            int last = n - 1 - layer;
            for(int i = first; i < last; i++) {
                int offset = i - first;
                int top = mat[first][i];
                mat[first][i] = mat[last - offset][first];
                mat[last - offset][first] = mat[last][last - offset];
                mat[last][last - offset] = mat[i][last];
                mat[i][last] = top;
            }
        }
        return mat;
    }
}
  • 1.7 清除行列

題目描述 請編寫一個演算法,若N階方陣中某個元素為0,則將其所在的行與列清零。

給定一個N階方陣int[]mat和矩陣的階數n,請返回完成操作後的int[][]方陣(C++中為vector>),保證n小於等於300,矩陣中的元素為int範圍內。

測試樣例:
[[1,2,3],[0,1,2],[0,0,1]]
返回:[[0,0,3],[0,0,0],[0,0,0]]

解法:這道題有個陷阱,如果直接遍歷整個矩陣,一旦發現0,就將其所在的行與列都清零,那麼後面在讀到被清零的行或列時,讀到的都是0. 可以考慮開兩個陣列,分別記錄包含零元素的所有行和列。

import java.util.*;

public class Clearer {
    public int[][] clearZero(int[][] mat, int n) {
        // write code here
        boolean[] row = new boolean[mat.length];
        boolean[] column = new boolean[mat[0].length];
        for(int i = 0; i < mat.length; i++) {
            for(int j = 0; j < mat[0].length; j++) {
                if(mat[i][j] == 0) {
                    row[i] = true;
                    column[j] = true;
                }
            }
        }
        for(int i = 0; i < mat.length; i++) {
            for(int j = 0; j < mat[0].length; j++) {
                if(row[i] || column[j]) {
                    mat[i][j] = 0;
                }
            }
        }
        return mat;
    }
}
  • 1.8 翻轉子串

假定我們都知道非常高效的演算法來檢查一個單詞是否為其他字串的子串。請將這個演算法編寫成一個函式,給定兩個字串s1和s2,請編寫程式碼檢查s2是否為s1旋轉而成,要求只能呼叫一次檢查子串的函式。

給定兩個字串s1,s2,請返回bool值代表s2是否由s1旋轉而成。字串中字元為英文字母和空格,區分大小寫,字串長度小於等於1000。

測試樣例:
"Hello world","worldhello "
返回:false
"waterbottle","erbottlewat"
返回:true

解法: 如果s2是s1+s1的子串,那麼s2一定可以由s1旋轉得到

import java.util.*;

public class ReverseEqual 
            
           

相關推薦

程式設計師面試題解

大部分試題在牛客網上測試通過,部分程式碼參考牛客網討論區。 連結串列 棧和佇列 樹和圖 位操作 數學和概率 排序和查詢 陣列和字串 1.1 確定字元互異 題目描述 請實現一個演算法,確定一個字串的所有字元是否全都不同。這裡

檢查是否是BST 牛客網 程式設計師面試 C++ java Python

檢查是否是BST 牛客網 程式設計師面試金典  C++ java Python 題目描述 請實現一個函式,檢查一棵二叉樹是否為二叉查詢樹。 給定樹的根結點指標TreeNode* root,請返回一

[JAVA程式設計師面試]最長遞增子序列

最簡單的思路是動態規劃,陣列array表示輸入的陣列,用一個數組dp記錄子串每一位的最長遞增子串長度,採用公式 dp[i]=max(dp[i],dp[j]+1)其中j<i,並且array[i]

上樓梯 牛客網 程式設計師面試 動態規劃

上樓梯 牛客網 程式設計師面試經典 動態規劃 題目描述 有個小孩正在上樓梯,樓梯有n階臺階,小孩一次可以上1階、2階、3階。請實現一個方法,計算小孩有多少種上樓的方式。為了防止溢位,請將結果Mo

程式設計師面試習題集錦02

尋找二進位制1的個數相等的最大和最小值 最笨的方法,就是暴力求解,全排列直接做 可以通過分析二進位制字串來實現尋找 直接異或,然後求解1的數量即可 我想到的最笨的方法就

程式設計師面試演算法題

空格替換 題目描述 請編寫一個方法,將字串中的空格全部替換為“%20”。假定該字串有足夠的空間存放新增的字元,並且知道字串的真實長度(小於等於1000),同時保證字串由大小寫的英文字母組成。 給定一個string iniString 為原始的串,以及串的長

程式設計師面試》--尋找二叉樹中兩個節點的第一個公共祖先(三種情況)

/**************************************************************************************************

牛客網程式設計師面試:1.1確定字元互異(java實現)

問題描述: 請實現一個演算法,確定一個字串的所有字元是否全都不同。這裡我們要求不允許使用額外的儲存結構。 給定一個string iniString,請返回一個bool值,True代表所有字元全都不同,False代表存在相同的字元。保證字串中的字元為A

程式設計師面試: 9.4樹與圖 4.2給定有向圖,設計一個演算法,找出兩個節點之間是否存在一條路徑。

#include <iostream> #include <stdio.h> #include <vector> #include <queue> using namespace std; /* 問題:給定有向圖,設計一個

程式設計師面試1.7:若M*N矩陣中某個元素為0,則將其所在的行與列清零

1.7:編寫一個演算法,若M*N矩陣中某個元素為0,則將其所在的行與列清零。 咋一看,這個問題很簡單:直接遍歷整個矩陣,只要發現值為0的元素,就將其所在的行與列清零。不過這種方法有個缺陷:在讀取被清零的行與列時,讀到的盡是零,於是所在的行與所在的列都變成了0,很快,整個矩陣

程式設計師面試: 9.14 Java 14.2在Java中,若在try-catch-finally的try語句塊中插入return語句,finally語句塊是否還會執行?

問題:在Java中,若在try-catch-finally的try語句塊中插入return語句,finally語句塊是否還會執行? 分析:不一定。如果在try語句中走到return語句之前都沒有發生異常,會走到return語句,就直接返回了。               如

程式設計師面試》--基本字串壓縮

題目描述:利用字元重複出現的次數,編寫一個方法,實現基本的字串壓縮功能。比如,字串“aabcccccaaa”經壓縮會變成“a2b1c5a3”。若壓縮後的字串沒有變短,則返回原先的字串。 給定一個str

[C/C++程式設計師面試] (07)-翻轉句子中單詞的順序

點選此處檢視原文 題目:輸入一個英文句子,翻轉句子中單詞的順序,但單詞內字元的順序不變。句子中單詞以空格符隔開。為簡單起見,標點符號和普通字母一樣處理。 例如輸入“I am a student.”,則輸出“student. a am I”。 分析:由於編寫字串相關程式碼能夠反映程式設計師

程式設計師面試(12)-從上往下遍歷二元樹

http://www.itmian4.com/thread-6009-1-1.html 題目:輸入一顆二元樹,從上往下按層列印樹的每個結點,同一層中按照從左往右的順序列印。 例如輸入          &n

程式設計師面試筆記(歐立奇版)

printf()函式計算引數是從右向左入棧的。 *(ptr++)+=123;含義為*ptr=*ptr+123;ptr++;//括號的優先順序比*低 float a=1.0f; cout<<(int&)a<<endl; //浮點數在記憶體裡和整數的儲存方式不同

程式設計師面試隨筆記(一)----計算機網路知識點梳理

傳輸層概 作用:傳輸層為它上面的應用層提供通訊服務。 在OSI七層參考模型中,傳輸層是面向通訊的最高層,也是使用者功能的最底層。 傳輸層兩大重要的功能:複用 和 分用。 複用:在傳送端,多個應

程式設計師面試隨筆記(一)--記憶體管理詳解

  記憶體管理是C++最令人切齒痛恨的問題,也是C++最有爭議的問題,C++高手從中獲得了更好的效能,更大的自由,C++菜鳥的收穫則是一遍一遍的檢查程式碼和對C++的痛恨,但記憶體管理在C++中無處不在,記憶體洩漏幾乎在每個C++程式中都會發生,因此要想成為C++高手,記

程式設計師面試隨筆記(一)---執行緒和程序1,-基礎資訊

①程式,程序,執行緒的區別 程式:程式是由一系列的指令和邏輯組成的一個靜態檔案(如cpp檔案),無論能不能執行,它都客觀的存在於儲存器中。 程序:程序是計算機中的程式關於某資料集合

最近整理的一些常見的面試題,面試大全,黑馬程式設計師面試題庫---最新技術--篇

第八章 最新技術(評論區留言獲取原件) 一、 Redis 1. Redis 的特點?        Redis 是由義大利人 Salvatore Sanfilippo(網名: antirez)開發的一款記憶體快取記憶體資料庫。 Redis

最近整理的一些常見的面試題,面試大全,黑馬程式設計師面試題庫---框架--篇

框架(評論留言獲取原件) 一、 SpringMVC 1. SpringMVC 的工作原理 a. 使用者向伺服器傳送請求,請求被 springMVC 前端控制器 DispatchServlet 捕獲; b. DispatcherServle 對請求 URL 進行解析,得到請求資源