双指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 fun reverseString (s: CharArray ) : Unit { var left = 0 var right = s.size - 1 while (left < right) { swap(s, left, right) left++ right-- } } fun swap (s: CharArray , left: Int , right: Int ) { val temp = s[left] s[left] = s[right] s[right] = temp }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fun reverseStr (s: String , k: Int ) : String { val charArray = s.toCharArray() for (i in s.indices step 2 * k) { var left = i var right = (i + k - 1 ) if (right > s.length - 1 ) { right = s.length - 1 } while (left < right) { LC344().swap(charArray, left, right) left++ right-- } } return String(charArray) }
随想录感觉解法不太好
https://leetcode.cn/problems/reverse-string-ii/solution/gong-shui-san-xie-jian-dan-zi-fu-chuan-m-p88f/
这个解法和我的差不多,更优雅
https://leetcode.cn/problems/ti-huan-kong-ge-lcof/solution/zhe-dao-ti-mu-zhen-de-you-zhe-yao-jian-dan-ma-qing/
这题的难点,主要就是去除 字符串中间的空格
栈或双端队列解法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 fun reverseWords (s: String ) : String { var left = 0 var right = s.length - 1 while (s[left] == ' ' ) { left++ } while (s[right] == ' ' ) { right-- } val deque: Deque<String> = ArrayDeque() val sb = StringBuilder() for (i in left..right) { if (s[left] != ' ' ) { sb.append(s[left]) } else if (s[left] == ' ' && sb.isNotEmpty()) { deque.offerFirst(sb.toString()) sb.setLength(0 ) } left++ } deque.offerFirst(sb.toString()) return java.lang.String.join(" " , deque) }
官方题解,文字版的感觉更好点,因为有java的版本的,视频的c++的不用stringbuilder
https://leetcode.cn/problems/reverse-words-in-a-string/solution/fan-zhuan-zi-fu-chuan-li-de-dan-ci-by-leetcode-sol/
两次反转字符串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 fun reverseWords2 (s: String ) : String { val sb = deleteStartEndSpace(s) reverseStringBuilder(sb, 0 , sb.length - 1 ) var wStart = 0 var wEnd = 0 while (wStart < sb.length) { if (sb.getOrElse(wEnd) { ' ' } == ' ' ) { reverseStringBuilder(sb, wStart, wEnd - 1 ) wStart = ++wEnd } else { wEnd++ } } return sb.toString() } private fun deleteStartEndSpace (s: String ) : StringBuilder { var left = 0 var right = s.length - 1 while (s[left] == ' ' ) { left++ } while (s[right] == ' ' ) { right-- } val sb = StringBuilder() while (left <= right) { if (s[left] != ' ' ) { sb.append(s[left]) } else if (s[left] == ' ' && s[left - 1 ] != ' ' ) { sb.append(s[left]) } left++ } return sb } private fun reverseStringBuilder (sb: StringBuilder , leftP: Int , rightP: Int ) { var left = leftP var right = rightP while (left < right) { val temp = sb[left] sb.setCharAt(left, sb[right]) sb.setCharAt(right, temp) left++ right-- } }
官方解法,翻转子字符串这种更妙
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;
}
}
数组System.arraycopy 深入分析用到了汇编指令,后面可以加强学习,其实底层的知识还是需要的,要不然没法深入下去了
https://blog.csdn.net/jackgo73/article/details/111866491
1 2 3 4 5 6 7 8 fun reverseLeftWords (s: String , n: Int ) : String { val sb = StringBuilder(s) for (i in 0 until n) { sb.append(s[i]) sb.deleteCharAt(0 ) } return sb.toString() }
不能申请额外空间,只能在本串上操作
我觉得用carl的方法更好
反转区间为前n的子串
反转区间为n到末尾的子串
反转整个字符串
https://programmercarl.com/%E5%89%91%E6%8C%87Offer58-II.%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC
暴力解法 aabaabaaf
aabaaf
整体移动底下的字串,然后匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 fun strStr (haystack: String , needle: String ) : Int { var needleIndex = 0 for (i in haystack.indices) { var hayIndex = i while (needleIndex < needle.length) { if (haystack.getOrNull(hayIndex) == needle[needleIndex]) { if (needleIndex == needle.length - 1 ) return i hayIndex++ needleIndex++ } else { needleIndex = 0 break } } } return -1 }
这个暴力解法,也有更好的写法
kmp https://noteforme.github.io/2021/06/17/kmp/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 fun strStrKmp (haystack: String , needle: String ) : Int { var j = 0 var nextArray = initNext(needle) for (i in haystack.indices) { while (j > 0 && haystack[i] != needle[j]) { j = nextArray[j - 1 ] } if (haystack[i] == needle[j]) { j++ } if (j == needle.length) { return i - j + 1 } } return -1 } fun initNext (needle: String ) : IntArray { var nextArray = IntArray(needle.length) var j = 0 for (i in 1 until needle.length) { while (j > 0 && needle[i] != needle[j]) { j = nextArray[j - 1 ] } if (needle[i] == needle[j]) j++ nextArray[i] = j } return nextArray }
这题根据随想录的 公式 套的
https://programmercarl.com/0459.%E9%87%8D%E5%A4%8D%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC
next[len - 1] = 7,next[len - 1] + 1 = 8 这句话的意思是. 这里数组统一减1,所以需要加1 == 8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 fun repeatedSubstringPattern (s: String ) : Boolean { val nxtArrr = initNext(s) val len = s.length if (nxtArrr[len - 1 ] != 0 && len % (len - nxtArrr[len - 1 ]) == 0 ) { return true } return false } private fun initNext (s: String ) : IntArray { var j = 0 val nxt = IntArray(s.length) nxt[0 ] = 0 for (i in 1 until s.length) { while (j > 0 && s[i] != s[j]) { j = nxt[j - 1 ] } if (s[i] == s[j]) j++ nxt[i] = j } return nxt }