LeetCode_字符串类
文章目錄
- 3.無(wú)重復(fù)字符的最長(zhǎng)子串
- 415.字符串相加
- 345.反轉(zhuǎn)字符串中的元音字母
- 14.最長(zhǎng)公共前綴
- 28.實(shí)現(xiàn)strStr()
- 58.最后一個(gè)單詞的長(zhǎng)度
- 67.二進(jìn)制求和
- 38.外觀數(shù)列
- 125.驗(yàn)證回文串
- 383.贖金信
- 387.字符串中的第一個(gè)唯一字符
- 434.字符串中的單詞數(shù)
- 443.壓縮字符串(沒懂)
- 459.重復(fù)的子字符串
- 520.檢測(cè)大寫字母
- 521.最長(zhǎng)特殊序列I
- 541.反轉(zhuǎn)字符串II
- 551.學(xué)生出勤記錄I
- 557.反轉(zhuǎn)字符串中的單詞III
- 680.驗(yàn)證回文字符串II
- 686.重復(fù)疊加字符串匹配
- 696.計(jì)數(shù)二進(jìn)制子串
- 面試題 01.09.字符串輪轉(zhuǎn)
- 面試題 01.06.字符串壓縮
- 788.旋轉(zhuǎn)數(shù)字
- 709.轉(zhuǎn)換成小寫字母
- 劍指Offer 58 - I.翻轉(zhuǎn)單詞順序
- 819.最常見的單詞(不懂 哈希映射)
- 917.僅僅反轉(zhuǎn)字母
- 859.親密字符串
- 336.回文對(duì)(一點(diǎn)不懂)
- 824,山羊拉丁文(沒看)
- ---------------------8.8-----------------------------
- 1071.字符串的最大公因子
- 1170.比較字符串最小字母出現(xiàn)頻次(看不懂啊)
- 1332.刪除回文子序列
- 1446.連續(xù)字符
- 劍指Offer 58 - II.左旋轉(zhuǎn)字符串(復(fù)習(xí))
- 面試題 01.04. 回文排列
- 上升下降字符串(沒寫)
- --------------------8.9-------------------
- 93.復(fù)原IP地址(沒看)
- 43.字符串相乘
- --------------8.13------------
- 1544.整理字符串
- 1507.轉(zhuǎn)變?nèi)掌诟袷?/li>
- 1455.檢查單詞是否為居中其他單詞的前綴
3.無(wú)重復(fù)字符的最長(zhǎng)子串
415.字符串相加
思路:
借鑒初學(xué)加法時(shí)的列豎式計(jì)算
345.反轉(zhuǎn)字符串中的元音字母
思路:
雙指針法,遇到元音字母交換
14.最長(zhǎng)公共前綴
class Solution {public String longestCommonPrefix(String[] strs) {if(strs.length == 0) return "";String ans = strs[0];for(int i =1;i<strs.length;i++) {int j=0;for(; j<ans.length()&&j < strs[i].length(); j++) { //ans.length?if(ans.charAt(j) != strs[i].charAt(j)) //charAt()返回指定索引處的字符break;}ans = ans.substring(0, j); //返回索引0~j-1處的字符if(ans.equals("")) //如果ans為空return ans;}return ans;} }28.實(shí)現(xiàn)strStr()
思路:
逐一比較
58.最后一個(gè)單詞的長(zhǎng)度
67.二進(jìn)制求和
class Solution {public String addBinary(String a, String b) {StringBuffer ans = new StringBuffer();int n = Math.max(a.length(), b.length()), carry = 0;for (int i = 0; i < n; ++i) {carry += i < a.length() ? (a.charAt(a.length() - 1 - i) - '0') : 0;carry += i < b.length() ? (b.charAt(b.length() - 1 - i) - '0') : 0;ans.append((char) (carry % 2 + '0'));carry /= 2;}if (carry > 0) {ans.append('1');}ans.reverse();return ans.toString();} }相關(guān)知識(shí)點(diǎn):
append():創(chuàng)建了一個(gè)新的數(shù)組,擴(kuò)大了長(zhǎng)度,將需要添加的字符串給復(fù)制到這個(gè)新的數(shù)組中
JAVA中Stringbuffer有append( )方法:
而Stringbuffer是動(dòng)態(tài)字符串?dāng)?shù)組,append( )是往動(dòng)態(tài)字符串?dāng)?shù)組添加,跟“xxxx”+“yyyy”相當(dāng)‘+’號(hào)。
跟String不同的是Stringbuffer是放一起的,String1+String2和Stringbuffer1.append(“yyyy”)雖然打印效果一樣,但在內(nèi)存中表示卻不一樣、
String1+String2 存在于不同的兩個(gè)地址內(nèi)存,Stringbuffer1.append(Stringbuffer2)放再一起。
StringBuffer是線程安全的,多用于多線程。
38.外觀數(shù)列
思路:
遞歸,StringBuffer
Java解法:
class Solution {public String countAndSay(int n) {if (n == 1) {return "1";}StringBuffer res = new StringBuffer();String str = countAndSay(n - 1); //遞歸 int length = str.length();int a = 0;for (int i = 1; i < length + 1; i++) {if (i == length) {return res.append(i - a).append(str.charAt(a)).toString();} else if (str.charAt(i) != str.charAt(a) ) {res.append(i - a).append(str.charAt(a));a = i;}}return res.toString(); //返回該對(duì)象的字符串表示} }125.驗(yàn)證回文串
思路:
方法二:
在原字符串上直接判斷
我們可以對(duì)方法一中第二種判斷回文串的方法進(jìn)行優(yōu)化,就可以得到只使用 O(1)O(1) 空間的算法。
我們直接在原字符串 ss 上使用雙指針。在移動(dòng)任意一個(gè)指針時(shí),需要不斷地向另一指針的方向移動(dòng),直到遇到一個(gè)字母或數(shù)字字符,或者兩指針重合為止。也就是說(shuō),我們每次將指針移到下一個(gè)字母字符或數(shù)字字符,再判斷這兩個(gè)指針指向的字符是否相同。
class Solution {public boolean isPalindrome(String s) {int n = s.length();int left = 0, right = n - 1;while (left < right) {while (left < right && !Character.isLetterOrDigit(s.charAt(left))) { //Character.isLetterOrDigit():含有字母。字符串++left;}while (left < right && !Character.isLetterOrDigit(s.charAt(right))) {--right;}if (left < right) {//Character.toLowerCase()將大寫轉(zhuǎn)換為小寫if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) {return false;}++left;--right;}}return true;} }383.贖金信
思路:
第一次遍歷,記錄ransonNote中字母出現(xiàn)的次數(shù);
第二次遍歷,記錄magazine中字母出現(xiàn)的次數(shù);
然后保證ransonNote中字母出現(xiàn)的次數(shù) <= magazine中相應(yīng)字母次數(shù)即可。
387.字符串中的第一個(gè)唯一字符
思路
兩個(gè)數(shù)組,一個(gè)記錄字母出現(xiàn)次數(shù),一個(gè)記錄字母第一次出現(xiàn)的位置,遍歷次數(shù)數(shù)組,次數(shù)為1的多個(gè)字母中,取最先出現(xiàn)的即索引值最小的
434.字符串中的單詞數(shù)
思路:
簡(jiǎn)單說(shuō),要設(shè)立個(gè)flag來(lái)判斷當(dāng)前遇到的空格是否就是一個(gè)單詞的分割符號(hào)。條件就是在這之前已經(jīng)出現(xiàn)過非空格的單詞了,flag置1。遇到空格就先判斷flag是不是1, 是1就算一個(gè)單詞,然后將flag置零。反之亦然。
443.壓縮字符串(沒懂)
思路:
用指針anchor指向連續(xù)塊的起始位置,用指針read指向不同于該連續(xù)塊字符的第一個(gè)位置,用write指針更新字符數(shù)組。
read-anchor即為連續(xù)塊長(zhǎng)度,若為1,則不寫入,一趟完成后讓anchor指向read,即繼續(xù)掃描下一連續(xù)塊。
459.重復(fù)的子字符串
思路:
如果您的字符串S包含一個(gè)重復(fù)的子字符串,那么這意味著您可以多次“移位和換行”您的字符串,并使其與原始字符串匹配。
例如:abcabc
移位一次:cabcab
移位兩次:bcabca
移位三次:abcabc
現(xiàn)在字符串和原字符串匹配了,所以可以得出結(jié)論存在重復(fù)的子串
基于這個(gè)思想,可以每次移動(dòng)k個(gè)字符,直到匹配移動(dòng)length - 1次。但是這樣對(duì)于重復(fù)字符串很長(zhǎng)的字符串,效率會(huì)非常低。在LeetCode中執(zhí)行時(shí)間超時(shí)了。
為了避免這種無(wú)用的環(huán)繞,可以創(chuàng)建一個(gè)新的字符串str,它等于原來(lái)的字符串S再加上S自身,這樣其實(shí)就包含了所有移動(dòng)的字符串。
比如字符串:S = acd,那么str = S + S = acdacd
acd移動(dòng)的可能:dac、cda。其實(shí)都包含在了str中了。就像一個(gè)滑動(dòng)窗口
一開始acd (acd) ,移動(dòng)一次ac(dac)d,移動(dòng)兩次a(cda)cd。循環(huán)結(jié)束
所以可以直接判斷str中去除首尾元素之后,是否包含自身元素。如果包含。則表明存在重復(fù)子串。
class Solution {public boolean repeatedSubstringPattern(String s) {String str = s + s;return str.substring(1, str.length() - 1).contains(s); } }暴力代碼如下:(沒看)(超出時(shí)間限制)
class Solution {//暴力代碼 public boolean repeatedSubstringPattern(String s) {for(int i = 1; i < s.length(); i++) {String str = rotate(s.toCharArray(),i);if(s.equals(str)) return true;}return false;}public String rotate(char[] nums, int k) {k = k % nums.length;reverse(nums, 0, nums.length - 1);reverse(nums, 0, k - 1);reverse(nums, k, nums.length - 1);return String.valueOf(nums);}public void reverse(char[] nums, int begin, int end) {int i = begin, j = end;while(i < j) {char temp = nums[i];nums[i++] = nums[j];nums[j--] = temp;}}}520.檢測(cè)大寫字母
思路:
首先把字符串轉(zhuǎn)變?yōu)槲覀兪煜さ淖址麛?shù)組
1.分析:題目中給的三種情況我們可以轉(zhuǎn)化一下思路
(1)全是大寫字母:大寫字母的個(gè)數(shù) = 字符數(shù)組長(zhǎng)度
(2)首字母大寫:大寫字母?jìng)€(gè)數(shù)為1,并且下標(biāo)為0
(3)全是小寫字母:大寫字母?jìng)€(gè)數(shù)為0
其他情況均返回false
2.問題就轉(zhuǎn)化為了遍歷數(shù)組,并統(tǒng)計(jì)大寫字母位置和下標(biāo)位置(其中只有大寫字母?jìng)€(gè)數(shù)為1的時(shí)候需要用到下標(biāo)的判斷)
3.進(jìn)行判斷
Java:
521.最長(zhǎng)特殊序列I
541.反轉(zhuǎn)字符串II
class Solution {public String reverseStr(String s, int k) {//將字符串中的字符轉(zhuǎn)換為一個(gè)字符數(shù)組char[] a = s.toCharArray(); //每個(gè)塊開始于2k的倍數(shù),也就是0,2k,4k,6k,...。//注:如果沒有足夠的字符,則并不需要翻轉(zhuǎn)這個(gè)塊 for (int start = 0; start < a.length; start += 2 * k) {int i = start, j = Math.min(start + k - 1, a.length - 1);//為了翻轉(zhuǎn)從i到j(luò)的字符塊,我們可以交換位于i++和j--的字符while (i < j) { char tmp = a[i];a[i++] = a[j];a[j--] = tmp;}}return new String(a);} }551.學(xué)生出勤記錄I
方法 1:
簡(jiǎn)單的解法 [Accepted]
解決這個(gè)問題最簡(jiǎn)單的方法就是同濟(jì)字符串中 AA 的數(shù)目并檢查 LLLLLL 是否是給定字符串的一個(gè)子串。如果 AA 的數(shù)目比 22 少且 LLLLLL 不是給定字符串的一個(gè)子串,那么返回 truetrue,否則返回 falsefalse。
Java 中indexOfindexOf 方法可以用來(lái)檢查一個(gè)串是否是另一個(gè)串的子串。如果找不到子串,那么返回 -1,否則返回這個(gè)字符串第一次出現(xiàn)的位置。
Java:
方法 2:
優(yōu)化的解法 [Accepted]
算法:
上述方法的一個(gè)優(yōu)化是當(dāng) AA 的數(shù)目有 22 個(gè)的時(shí)候就中斷循環(huán)。
557.反轉(zhuǎn)字符串中的單詞III
思路:
1、找出空格并將空格前的單詞翻轉(zhuǎn)
2、最后一位的時(shí)候,將前面單詞翻轉(zhuǎn)
680.驗(yàn)證回文字符串II
686.重復(fù)疊加字符串匹配
class Solution {public int repeatedStringMatch(String A, String B) {int sum=A.length();for(int i=0;i<10000;i++){A=A+A.charAt(i);}int number;//B中字符第一次出現(xiàn)的索引int num=A.indexOf(B); if(num==-1)return -1;//number:B最后一個(gè)字符在A中的索引number=num+B.length();if(number%sum==0) //!!!!return number/sum;elsereturn number/sum+1;} }696.計(jì)數(shù)二進(jìn)制子串
面試題 01.09.字符串輪轉(zhuǎn)
思路:
長(zhǎng)度相等時(shí),若s2是s1旋轉(zhuǎn)而成的,那么把s2和自身拼接一次,s1就會(huì)出現(xiàn)在其中
“erbottlewat” + “erbottlewat” = erbottle waterbottle wat
如果s2不是s1旋轉(zhuǎn)而成的,那么那么把s2和自身拼接一次,s1就肯定不會(huì)出現(xiàn)在其中
面試題 01.06.字符串壓縮
class Solution {/** *前后雙指針 *O(n) *O(1) */ public String compressString(String S) {int len =S.length();if(S==null||len<=1) return S;//StringBuilder:一個(gè)可變的字符序列StringBuilder sb = new StringBuilder(); //快慢前后雙指針int l=0,r=1;while(r<len){if(S.charAt(r)!=S.charAt(l)){//append()創(chuàng)建了一個(gè)新的數(shù)組,擴(kuò)大了長(zhǎng)度,將需要添加的字符串添加到這個(gè)新的數(shù)組中sb.append(S.charAt(l));sb.append((r-l)+"");l=r;r+=1;}else{r++;}}//最后一個(gè)相同的字符sb.append(S.charAt(l));sb.append((r-l)+"");//和原字符串比較長(zhǎng)度return sb.length()>=len?S:sb.toString(); }}788.旋轉(zhuǎn)數(shù)字
709.轉(zhuǎn)換成小寫字母
思路1:
思路2:
學(xué)習(xí)使用isupper和tolower函數(shù),提高程序可讀性
劍指Offer 58 - I.翻轉(zhuǎn)單詞順序
PS:strim(),StringBuilder,append(),toString(),charAt()
819.最常見的單詞(不懂 哈希映射)
917.僅僅反轉(zhuǎn)字母
**方法 1:**字母棧
想法和算法
將 s 中的所有字母單獨(dú)存入棧中,所以出棧等價(jià)于對(duì)字母反序操作。(或者,可以用數(shù)組存儲(chǔ)字母并反序數(shù)組。)
然后,遍歷 s 的所有字符,如果是字母我們就選擇棧頂元素輸出
class Solution {public String reverseOnlyLetters(String S) {Stack<Character> letters = new Stack();for (char c: S.toCharArray()){//isLetter():判定自定字符是否為字母//push():把對(duì)象壓入堆棧的頂部if (Character.isLetter(c))letters.push(c);}StringBuilder ans = new StringBuilder();for (char c: S.toCharArray()) {if (Character.isLetter(c))//pop:從集合中把最后一個(gè)元素刪除,并返回這個(gè)元素的值ans.append(letters.pop());elseans.append(c);}return ans.toString();} }859.親密字符串
336.回文對(duì)(一點(diǎn)不懂)
涉及知識(shí):
字典樹,哈希表
824,山羊拉丁文(沒看)
---------------------8.8-----------------------------
1071.字符串的最大公因子
圖片解釋
1170.比較字符串最小字母出現(xiàn)頻次(看不懂啊)
1332.刪除回文子序列
思路:
只有三種情況:
1.空字符串:刪除0次
2.回文字符串:刪除1次
3.非回文串 刪除2次(一次全部刪除a,一次全部刪除b)
1446.連續(xù)字符
注:
子串:指的是串中任意個(gè)連續(xù)的字符組成的子序列,稱為改串的子串
子序列:可以是不連續(xù)的
思路:
連續(xù)相同的字符確定一個(gè)區(qū)間[left,i)。
left是區(qū)間左邊界。
i是當(dāng)前遍歷的字符。
當(dāng)A[i] != A[left]時(shí),表示區(qū)間[left,i)結(jié)束。i-left就是區(qū)間長(zhǎng)度,就是可能的解之一。
容易錯(cuò)的地方在于最后一個(gè)區(qū)間[left,A.length),沒有處理。
當(dāng)i == A.length時(shí),循環(huán)結(jié)束。忘記統(tǒng)計(jì)此區(qū)間的長(zhǎng)度,丟失解。
劍指Offer 58 - II.左旋轉(zhuǎn)字符串(復(fù)習(xí))
class Solution {public String reverseLeftWords(String s, int n) {return s.substring(n, s.length()) + s.substring(0, n);} }注:
收藏夾里 多種解法很有意義 還沒有仔細(xì)看
面試題 01.04. 回文排列
思路:
構(gòu)成回文的字符串,相同字符的個(gè)數(shù)中,最多有一個(gè)是奇數(shù)。超過一個(gè),則不是回文串
上升下降字符串(沒寫)
--------------------8.9-------------------
93.復(fù)原IP地址(沒看)
#define SEG_COUNT 4 int segments[SEG_COUNT]; char** ans; int ans_len;void dfs(char* s, int segId, int segStart) {// 如果找到了 4 段 IP 地址并且遍歷完了字符串,那么就是一種答案int len_s = strlen(s);if (segId == SEG_COUNT) {if (segStart == len_s) {char* ipAddr = (char*)malloc(sizeof(char) * (len_s + 4));int add = 0;for (int i = 0; i < SEG_COUNT; ++i) {int number = segments[i];if (number >= 100) {ipAddr[add++] = number / 100 + '0';}if (number >= 10) {ipAddr[add++] = number % 100 / 10 + '0';}ipAddr[add++] = number % 10 + '0';if (i != SEG_COUNT - 1) {ipAddr[add++] = '.';}}ipAddr[add] = 0;ans = realloc(ans, sizeof(char*) * (ans_len + 1));ans[ans_len++] = ipAddr;}return;}// 如果還沒有找到 4 段 IP 地址就已經(jīng)遍歷完了字符串,那么提前回溯if (segStart == len_s) {return;}// 由于不能有前導(dǎo)零,如果當(dāng)前數(shù)字為 0,那么這一段 IP 地址只能為 0if (s[segStart] == '0') {segments[segId] = 0;dfs(s, segId + 1, segStart + 1);}// 一般情況,枚舉每一種可能性并遞歸int addr = 0;for (int segEnd = segStart; segEnd < len_s; ++segEnd) {addr = addr * 10 + (s[segEnd] - '0');if (addr > 0 && addr <= 0xFF) {segments[segId] = addr;dfs(s, segId + 1, segEnd + 1);} else {break;}} }char** restoreIpAddresses(char* s, int* returnSize) {ans = (char**)malloc(0);ans_len = 0;dfs(s, 0, 0);(*returnSize) = ans_len;return ans; }43.字符串相乘
--------------8.13------------
1544.整理字符串
Java:
思路一:從頭遍歷,依次將字符串s的字符入棧,如果當(dāng)前字符使棧頂字符對(duì)應(yīng)的大小寫,則將棧頂元素彈出即可
C:
1507.轉(zhuǎn)變?nèi)掌诟袷?/h1>
1455.檢查單詞是否為居中其他單詞的前綴
int isPrefixOfWord(char * sentence, char * searchWord){int i=0;if(*sentence==*searchWord) //這個(gè)的作用是判斷第一個(gè)是否符合要求,因?yàn)槲沂且钥崭駷闃?biāo)志的{ //而第一個(gè)單詞前面是沒有空格的while(searchWord[i]){if(searchWord[i]!=sentence[i]){break;}i++;}if(searchWord[i]==NULL)return 1;}int j=0;int count=1; //count是計(jì)算的是第幾個(gè)單詞while(sentence[i]) //遇到空格就對(duì)后續(xù)進(jìn)行判斷{ if(sentence[i]==' '){i++;count++;while(searchWord[j]){if(searchWord[j]!=sentence[i+j]){break;}j++;}if(searchWord[j]==NULL){return count;}j=0;}i++;}return -1; }總結(jié)
以上是生活随笔為你收集整理的LeetCode_字符串类的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LeetCode_链表类
- 下一篇: String、StringBuffer比