字符串——面試考察高頻算法題

目錄

轉換成小寫字母

字符串轉化為整數

反轉相關的問題

反轉字符串

k個一組反轉

僅僅反轉字母

反轉字符串里的單詞

驗證回文串

判斷是否互為字符重排

最長公共前綴

字符串壓縮問題


轉換成小寫字母

給你一個字符串 s ,將該字符串中的大寫字母轉換成相同的小寫字母,返回新的字符串。

每個字母都是有確定的 ASCII的,因此我們可以根據 碼表操作字符串即可。

常見ASCII范圍是:

  • a-z:97-122

  • A-Z:65-90

  • 0-9:48-57

public static String toLowerCase(String s) {int n = s.length();char[] chars = s.toCharArray();for (int i = 0; i < n; ++i) {if (chars[i] >= 65 && chars[i] <= 90) {chars[i] += 32;}}String str = new String(chars);return str;
}

字符串轉化為整數

請你來實現一個 myAtoi(string s) 函數,使其能將字符串轉換成一個 32 位有符號整數

函數 myAtoi(string s) 的算法如下:

  1. 空格:讀入字符串并丟棄無用的前導空格(" "

  2. 符號:檢查下一個字符(假設還未到字符末尾)為 '-' 還是 '+'。如果兩者都不存在,則假定結果為正。

  3. 轉換:通過跳過前置零來讀取該整數,直到遇到非數字字符或到達字符串的結尾。如果沒有讀取數字,則結果為0。

  4. 舍入:如果整數數超過 32 位有符號整數范圍 [?2(31), 2(31 )? 1] ,需要截斷這個整數,使其保持在這個范圍內。具體來說,小于 ?2(31) 的整數應該被舍入為 ?2(31) ,大于 2(31 )? 1 的整數應該被舍入為 2(31 )? 1

返回整數作為最終結果。

public static int myAtoi(String str) {int len = str.length();char[] charArray = str.toCharArray();// 1、去除前導空格int index = 0;while (index < len && charArray[index] == ' ') {index++;}// 2、如果已經遍歷完成(針對極端用例 "      ")if (index == len) {return 0;}// 3、如果出現符號字符,僅第 1 個有效,并記錄正負int sign = 1;char firstChar = charArray[index];if (firstChar == '+') {index++;} else if (firstChar == '-') {index++;sign = -1;}// 4、將后續出現的數字字符進行轉換// 不能使用 long 類型,這是題目說的int res = 0;while (index < len) {char currChar = charArray[index];// 4.1 先判斷不合法的情況if (currChar > '9' || currChar < '0') {break;}// 這是解決溢出問題的經典處理方式。if (res > Integer.MAX_VALUE / 10 || (res == Integer.MAX_VALUE / 10 && (currChar - '0') > Integer.MAX_VALUE % 10)) {return Integer.MAX_VALUE;}if (res < Integer.MIN_VALUE / 10 || (res == Integer.MIN_VALUE / 10 && (currChar - '0') > -(Integer.MIN_VALUE % 10))) {return Integer.MIN_VALUE;}// 合法的情況下,才考慮轉換,每一步都把符號位乘進去// 想想這里為什么要帶著sign乘res = res * 10 + sign * (currChar - '0');index++;}return res;
}

反轉相關的問題

反轉字符串

編寫一個函數,其作用是將輸入的字符串反轉過來。輸入字符串以字符數組 s 的形式給出。

不要給另外的數組分配額外的空間,你必須原地修改輸入數組、使用 O(1) 的額外空間解決這一問題。

  • 一看就是雙指針問題!太經典了!

public void reverseString(char[] s) {if (s == null || s.length() == 0) {return ;}int n = s.length;for (int left = 0, right = n - 1; left < right; ++left, --right) {char tmp = s[left];s[left] = s[right];s[right] = tmp;}}

k個一組反轉

給定一個字符串 s 和一個整數 k,從字符串開頭算起,每計數至 2k 個字符,就反轉這 2k 字符中的前 k 個字符。

  • 如果剩余字符少于 k 個,則將剩余字符全部反轉。

  • 如果剩余字符小于 2k 但大于或等于 k 個,則反轉前 k 個字符,其余字符保持原樣。

反轉每個下標從 2k的倍數開始的,長度為 k的子串。若該子串長度不足 k,則反轉整個子串。

public String reverseStr(String s, int k) {if (s == null || s.length() == 0) {return s;}int n = s.length();char[] arr = s.toCharArray();for (int i = 0; i < n; i += 2 * k) {reverse(arr, i, Math.min(i + k, n) - 1);}return new String(arr);}public void reverse(char[] arr, int left, int right) {while (left < right) {char temp = arr[left];arr[left] = arr[right];arr[right] = temp;left++;right--;}}

僅僅反轉字母

給定一個字符串 S,返回 “反轉后的” 字符串,其中不是字母的字符都保留在原地,而所有字母的位置發生反轉。

示例1:

輸入:"ab-cd"

輸出:"dc-ba"

示例2:

輸入:"a-bC-dEf-ghIj"

輸出:"j-Ih-gfE-dCba"

示例3:

輸入:"Test1ng-Leet=code-Q!"

輸出:"Qedo1ct-eeLg=ntse-T!"

  • 棧:將 s 中的所有字母單獨存入棧中,所以出棧等價于對字母反序操作。(或者可以用數組存儲字母并反序數組)然后,遍歷 s 的所有字符,如果是字母我們就選擇棧頂元素輸出。

  • 雙指針:一個接一個輸出 s 的所有字符。當遇到一個字母時,我們希望找到逆序遍歷字符串的下一個字母。所以我們這么做:維護一個指針 j 從后往前遍歷字符串,當需要字母時就使用它。

class Solution {public String reverseOnlyLetters(String S) {Stack<Character> letters = new Stack();for (char c: S.toCharArray())if (Character.isLetter(c))letters.push(c);StringBuilder ans = new StringBuilder();for (char c: S.toCharArray()) {if (Character.isLetter(c))ans.append(letters.pop());elseans.append(c);}return ans.toString();}
}
class Solution {public String reverseOnlyLetters(String S) {if (S == null || S.length() == 0) {return S;}StringBuilder ans = new StringBuilder();int j = S.length() - 1;for (int i = 0; i < S.length(); ++i) {if (Character.isLetter(S.charAt(i))) {while (!Character.isLetter(S.charAt(j)))j--;ans.append(S.charAt(j--));} else {ans.append(S.charAt(i));}}return ans.toString();}
}

反轉字符串里的單詞

給你一個字符串 s ,逐個反轉字符串中的所有 單詞

單詞 是由非空格字符組成的字符串。s 中使用至少一個空格將字符串中的 單詞 分隔開。

請你返回一個反轉 s 中單詞順序并用單個空格相連的字符串

說明:

  • 輸入字符串 s 可以在前面、后面或者單詞間包含多余的空格。

  • 反轉后單詞間應當僅用一個空格分隔。

  • 反轉后的字符串中不應包含額外的空格。

示例1:

輸入:s = "the sky is blue"

輸出:"blue is sky the"

示例2:

輸入:s = "hello world"

輸出:"world hello"

解釋:輸入字符串可以在前面或者后面包含多余的空格,但是反轉后的字符不能包括。

 
public String reverseWords(String s) {if (s == null || s.length() == 0) {return s;}// 除去開頭和末尾的空白字符,記住這個操作s = s.trim();// 正則匹配連續的空白字符作為分隔符分割List<String> wordList = Arrays.asList(s.split("\\s+"));Collections.reverse(wordList);return String.join(" ", wordList);}

 
class Solution {public String reverseWords(String s) {StringBuilder sb = trimSpaces(s);// 翻轉字符串reverse(sb, 0, sb.length() - 1);// 翻轉每個單詞reverseEachWord(sb);return sb.toString();}public StringBuilder trimSpaces(String s) {int left = 0, right = s.length() - 1;// 去掉字符串開頭的空白字符while (left <= right && s.charAt(left) == ' ') {++left;}// 去掉字符串末尾的空白字符while (left <= right && s.charAt(right) == ' ') {--right;}// 將字符串間多余的空白字符去除StringBuilder sb = new StringBuilder();while (left <= right) {char c = s.charAt(left);if (c != ' ') {sb.append(c);} else if (sb.charAt(sb.length() - 1) != ' ') {sb.append(c);}++left;}return sb;}public void reverse(StringBuilder sb, int left, int right) {while (left < right) {char tmp = sb.charAt(left);sb.setCharAt(left++, sb.charAt(right));sb.setCharAt(right--, tmp);}}public void reverseEachWord(StringBuilder sb) {int n = sb.length();int start = 0, end = 0;while (start < n) {// 循環至單詞的末尾while (end < n && sb.charAt(end) != ' ') {++end;}// 翻轉單詞reverse(sb, start, end - 1);// 更新start,去找下一個單詞start = end + 1;++end;}}
}

驗證回文串

給定一個字符串,找到它的第一個不重復的字符,并返回它的索引。如果不存在,則返回 -1。

  • 在第一次遍歷時,我們使用哈希映射統計出字符串中每個字符出現的次數。在第二次遍歷時,我們只要遍歷到了一個只出現一次的字符,那么就返回它的索引,否則在遍歷結束后返回 -1。

public int firstUniqChar(String s) {if (s == null || s.length() == 0) {return 0;}Map<Character, Integer> frequency = new HashMap<Character, Integer>();for (int i = 0; i < s.length(); ++i) {char ch = s.charAt(i);frequency.put(ch, frequency.getOrDefault(ch, 0) + 1);}for (int i = 0; i < s.length(); ++i) {if (frequency.get(s.charAt(i)) == 1) {return i;}}return -1;}

判斷是否互為字符重排

給定兩個字符串 s1 和 s2,請編寫一個程序,確定其中一個字符串的字符重新排列后,能否變成另一個字符串。

  • 將兩個字符串全部從小到大或者從大到小排列,然后再逐個位置比較

  • 我們可以記錄出現的次數,如果一個字符串經過重新排列后,能夠變成另外一個字符串,那么它們的每個不同字符的出現次數是相同的。如果出現次數不同,那么表示兩個字符串不能夠經過重新排列得到。

public boolean checkPermutation(String s1, String s2) {// 將字符串轉換成字符數組char[] s1Chars = s1.toCharArray();char[] s2Chars = s2.toCharArray();// 對字符數組進行排序Arrays.sort(s1Chars);Arrays.sort(s2Chars);// 再將字符數組轉換成字符串,比較是否相等return new String(s1Chars).equals(new String(s2Chars));}

 
public boolean checkPermutation(String s1, String s2) {if (s1.length() != s2.length()) {return false;}char[] s1Chars = s1.toCharArray();Map<Character, Integer> s1Map = getMap(s1);Map<Character, Integer> s2Map = getMap(s2);for (char s1Char : s1Chars) {if (!s2Map.containsKey(s1Char) || (int)s2Map.get(s1Char) != (int)s1Map.get(s1Char)) {return false;}}return true;}// 統計指定字符串str中各字符的出現次數,并以Map的形式返回private Map<Character, Integer> getMap(String str) {Map<Character, Integer> map = new HashMap<>();char[] chars = str.toCharArray();for (char aChar : chars) {map.put(aChar, map.getOrDefault(aChar, 0) + 1);}return map;}

最長公共前綴

編寫一個函數來查找字符串數組中的最長公共前綴。如果不存在公共前綴,返回空字符串 ""。

示例1:

輸入:strs = ["flower","flow","flight"]

輸出:"fl"

示例2:

輸入:strs = ["dog","racecar","car"]

輸出:""

解釋:輸入不存在公共前綴。

  • 豎著比較,每前進一個位置就比較各個串,看是不是都是相等的,只要在某一輪遇到一個不相等的,那么就結束。

  • 橫著比較,借鑒歸并的思想,先兩兩一組找fix,然后將找到的fix再兩兩歸并。依次遍歷字符串數組中的每個字符串,對于每個遍歷到的字符串,更新最長公共前綴(其實就是看是否要縮短,一定不會變長),當遍歷完所有的字符串以后,即可得到字符串數組中的最長公共前綴。如果在尚未遍歷完所有的字符串時,最長公共前綴已經是空串,則最長公共前綴一定是空串,因此不需要繼續遍歷剩下的字符串,直接返回空串即可。

 
public String longestCommonPrefix(String[] strs) {if (strs == null || strs.length == 0) {return "";}int length = strs[0].length();int count = strs.length;for (int i = 0; i < length; i++) {char c = strs[0].charAt(i);for (int j = 1; j < count; j++) {if (i == strs[j].length() || strs[j].charAt(i) != c) {return strs[0].substring(0, i);}}}return strs[0];

 
public String longestCommonPrefix(String[] strs) {if (strs == null || strs.length == 0) {return "";}String prefix = strs[0];int count = strs.length;for (int i = 1; i < count; i++) {prefix = longestCommonPrefix(prefix, strs[i]);if (prefix.length() == 0) {break;}}return prefix;
}public String longestCommonPrefix(String str1, String str2) {int length = Math.min(str1.length(), str2.length());int index = 0;while (index < length && str1.charAt(index) == str2.charAt(index)) {index++;}return str1.substring(0, index);
}

字符串壓縮問題

給你一個字符數組 chars ,請使用下述算法壓縮:

從一個空字符串 s 開始。對于 chars 中的每組 連續重復字符 :

  • 如果這一組長度為 1 ,則將字符追加到 s 中。

  • 否則,需要向 s 追加字符,后跟這一組的長度。壓縮后得到的字符串 s 不應該直接返回 ,需要轉儲到字符數組 chars 中。需要注意的是,如果組長度為 10 或 10 以上,則在 chars 數組中會被拆分為多個字符。

請在 修改完輸入數組后 ,返回該數組的新長度。你必須設計并實現一個只使用常量額外空間的算法來解決此問題。

 
示例1:
輸入:chars = ["a","a","b","b","c","c","c"]
輸出:返回 6 ,輸入數組的前 6 個字符應該是:["a","2","b","2","c","3"]
解釋:
"aa" 被 "a2" 替代。"bb" 被 "b2" 替代。"ccc" 被 "c3" 替代。示例2:
輸入:chars = ["a"]
輸出:返回 1 ,輸入數組的前 1 個字符應該是:["a"]
解釋:
沒有任何字符串被替代。示例3:
輸入:chars = ["a","b","b","b","b","b","b","b","b","b","b","b","b"]
輸出:返回 4 ,輸入數組的前 4 個字符應該是:["a","b","1","2"]。
解釋:
由于字符 "a" 不重復,所以不會被壓縮。"bbbbbbbbbbbb" 被 “b12” 替代。
注意每個數字在數組中都有它自己的位置。

  • 可以使用兩個指針分別標志我們在字符串中讀和寫的位置,還要一個指針left用來標記重復字段的開始位置。read指針不斷向前讀取,每次當讀指針 read 移動到某一段連續相同子串的最右側,我們就在寫指針 write 處依次寫入該子串對應的字符和子串長度即可。當讀指針read 位于字符串的末尾,或讀指針read 指向的字符不同于下一個字符時,我們就認為讀指針read 位于某一段連續相同子串的最右側。該子串對應的字符即為讀指針 read 指向的字符串。我們使用變量 left 記錄該子串的最左側的位置,這樣子串長度即為 read?left+1。這里還有一個問題,就是長度可能超過10,因此還要實現將數字轉化為字符串寫入到原字符串的功能。這里我們采用短除法將子串長度倒序寫入原字符串中,然后再將其反轉即可。

public int compress(char[] chars) {int n = chars.length;int write = 0, left = 0;for (int read = 0; read < n; read++) {if (read == n - 1 || chars[read] != chars[read + 1]) {chars[write++] = chars[read];int num = read - left + 1;if (num > 1) {int anchor = write;while (num > 0) {chars[write++] = (char) (num % 10 + '0');num /= 10;}reverse(chars, anchor, write - 1);}left = read + 1;}}return write;}public void reverse(char[] chars, int left, int right) {while (left < right) {char temp = chars[left];chars[left] = chars[right];chars[right] = temp;left++;right--;}}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/74645.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/74645.shtml
英文地址,請注明出處:http://en.pswp.cn/web/74645.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

現代復古電影海報品牌徽標設計襯線英文字體安裝包 Thick – Retro Vintage Cinematic Font

Thick 是一種大膽的復古字體&#xff0c;專為有影響力的標題和懷舊的視覺效果而設計。其厚實的字體、復古魅力和電影風格使其成為電影海報、產品標簽、活動品牌和編輯設計的理想選擇。無論您是在引導電影的黃金時代&#xff0c;還是在現代布局中注入復古活力&#xff0c;Thick …

[C++面試] new、delete相關面試點

一、入門 1、說說new與malloc的基本用途 int* p1 (int*)malloc(sizeof(int)); // C風格 int* p2 new int(10); // C風格&#xff0c;初始化為10 new 是 C 中的運算符&#xff0c;用于在堆上動態分配內存并調用對象的構造函數&#xff0c;會自動計算所需內存…

Unity URP管線與HDRP管線對比

1. 渲染架構與底層技術 URP 渲染路徑&#xff1a; 前向渲染&#xff08;Forward&#xff09;&#xff1a;默認單Pass前向&#xff0c;支持少量實時光源&#xff08;通常4-8個逐物體&#xff09;。 延遲渲染&#xff08;Deferred&#xff09;&#xff1a;可選但功能簡化&#…

JDK8卸載與安裝教程(超詳細)

JDK8卸載與安裝教程&#xff08;超詳細&#xff09; 最近學習一個項目&#xff0c;需要使用更高級的JDK&#xff0c;這里記錄一下卸載舊版本與安裝新版本JDK的過程。 JDK8卸載 以windows10操作系統為例&#xff0c;使用快捷鍵winR輸入cmd&#xff0c;打開控制臺窗口&#xf…

python爬蟲:DrissionPage實戰教程

如果本文章看不懂可以看看上一篇文章&#xff0c;加強自己的基礎&#xff1a;爬蟲自動化工具&#xff1a;DrissionPage-CSDN博客 案例解析&#xff1a; 前提&#xff1a;我們以ChromiumPage為主&#xff0c;寫代碼工具使用Pycharm&#xff08;python環境3.9-3.10&#xff09; …

07-01-自考數據結構(20331)- 排序-內部排序知識點

內部排序算法是數據結構核心內容,主要包括插入類(直接插入、希爾)、交換類(冒泡、快速)、選擇類(簡單選擇、堆)、歸并和基數五大類排序方法。 知識拓撲 知識點介紹 直接插入排序 定義:將每個待排序元素插入到已排序序列的適當位置 算法步驟: 從第二個元素開始遍歷…

Go語言-初學者日記(八):構建、部署與 Docker 化

&#x1f9f1; 一、go build&#xff1a;最基礎的構建方式 Go 的構建工具鏈是出了名的輕量、簡潔&#xff0c;直接用 go build 就能把項目編譯成二進制文件。 ? 構建當前項目 go build -o myapp-o myapp 指定輸出文件名默認會構建當前目錄下的 main.go 或 package main &a…

教程:如何使用 JSON 合并腳本

目錄 1. 介紹 2. 使用方法 3. 注意事項 4. 示例 5.完整代碼 1. 介紹 該腳本用于將多個 COCO 格式的 JSON 標注文件合并為一個 JSON 文件。COCO 格式常用于目標檢測和圖像分割任務&#xff0c;包含以下三個主要部分&#xff1a; "images"&#xff1a;圖像信息&a…

Java學習總結-緩沖流性能分析

測試用例&#xff1a; 分別使用原始的字節流&#xff0c;以及字節緩沖流復制一個很大的視頻。 測試步驟&#xff1a; 在這個分析性能需要一個記錄時間的工具&#xff1a;這個是記錄1970-1-1 00&#xff1a;00&#xff1a;00到現在的總毫秒值。 long start System.currentT…

流影---開源網絡流量分析平臺(五)(成果展示)

目錄 前沿 攻擊過程 前沿 前四章我們已經成功安裝了流影的各個功能&#xff0c;那么接下來我們就看看這個開源工具的實力&#xff0c;本實驗將進行多個攻擊手段&#xff08;ip掃描&#xff0c;端口掃描&#xff0c;sql注入&#xff09;攻擊靶機&#xff0c;來看看流影的態感效…

vs環境中編譯osg以及osgQt

1、下載 OpenSceneGraph 獲取源代碼 您可以通過以下方式獲取 OSG 源代碼: 官網下載:https://github.com/openscenegraph/OpenSceneGraph/releases 使用 git 克隆: git clone https://github.com/openscenegraph/OpenSceneGraph.git 2、下載必要的第三方依賴庫 依賴庫 ht…

Unity:標簽(tags)

為什么需要Tags&#xff1f; 在游戲開發中&#xff0c;游戲對象&#xff08;GameObject&#xff09;數量可能非常多&#xff0c;比如玩家、敵人、子彈等。開發者需要一種簡單的方法來區分這些對象&#xff0c;并根據它們的類型執行不同的邏輯。 核心需求&#xff1a; 分類和管…

【C++11】lambda

lambda lambda表達式語法 lambda表達式本質是一個匿名函數對象&#xff0c;跟普通函數不同的是它可以定義在函數內部。lambda表達式語法使用層而言沒有類型&#xff0c;所以一般是用auto或者模板參數定義的對象去接收lambda對象。 lambda表達式的格式&#xff1a;[capture-l…

fpga:分秒計時器

任務目標 分秒計數器核心功能&#xff1a;實現從00:00到59:59的循環計數&#xff0c;通過四個七段數碼管顯示分鐘和秒。 復位功能&#xff1a;支持硬件復位&#xff0c;將計數器歸零并顯示00:00。 啟動/暫停控制&#xff1a;通過按鍵控制計時的啟動和暫停。 消抖處理&#…

《UNIX網絡編程卷1:套接字聯網API》第6章 IO復用:select和poll函數

《UNIX網絡編程卷1&#xff1a;套接字聯網API》第6章 I/O復用&#xff1a;select和poll函數 6.1 I/O復用的核心價值與適用場景 I/O復用是高并發網絡編程的基石&#xff0c;允許單個進程/線程同時監控多個文件描述符&#xff08;套接字&#xff09;的狀態變化&#xff0c;從而高…

SpringBoot+vue前后端分離整合sa-token(無cookie登錄態 詳細的登錄流程)

SpringBootvue前后端分離整合sa-token&#xff08;無cookie登錄態 & 詳細的登錄流程&#xff09; 1.介紹sa-token1.1 框架定位1.2 核心優勢 2.如何整合sa-token3.如何進行無cookie模式登錄3.1后端3.1.1 VO層3.1.2 Controller層3.1.3 Service層 3.2前端3.2.1 登錄按鈕自定義…

MYOJ_1171:(洛谷P1075)[NOIP 2012 普及組] 質因數分解(數學相關,質數與約數基礎)

題目描述 已知正整數 n 是兩個不同的質數的乘積&#xff0c;試求出兩者中較大的那個質數。 1≤n≤210^9 輸入 輸入一個正整數 n。 輸出 輸出一個正整數 p&#xff0c;即較大的那個質數。 樣例輸入輸出 輸入&#xff1a;21 輸出&#xff1a;7 思路: 為了節約時間與…

Python語言的測試用例設計

Python語言的測試用例設計 引言 隨著軟件開發的不斷進步&#xff0c;測試在軟件開發生命周期中的重要性日益凸顯。測試用例設計是軟件測試的核心&#xff0c;它為軟件系統的驗證和驗證提供了實施的基礎。在Python語言中&#xff0c;由于其簡潔明了的語法和強大的內置庫&#…

SpringKafka消息消費:@KafkaListener與消費組配置

文章目錄 引言一、Spring Kafka消費者基礎配置二、KafkaListener注解使用三、消費組配置與負載均衡四、手動提交偏移量五、錯誤處理與重試機制總結 引言 Apache Kafka作為高吞吐量的分布式消息系統&#xff0c;在大數據處理和微服務架構中扮演著關鍵角色。Spring Kafka為Java開…

VMware 虛報化Ubuntu 卡成一B,如何接招?

故事背景 Win10 專業版 安裝VMware pro ,虛擬化出一個Window10&#xff0c;另一個是UBuntu.自從使用起來去不去就卡死。開始是以為驅動或者升級造成的&#xff0c;重新安裝一段時間問題照舊。更氣人的這種現象具有不定期性&#xff0c;說不定什么時候就來這么一出。 直接解決方…