1.14. 最长公共前缀
-
编写一个函数来查找字符串数组中的最长公共前缀。
-
如果不存在公共前缀,返回空字符串 “”。
1.解题思路(横向对比)
- 1.新建变量comm储存当前的公共前缀,初始化为字符串数组的元素;
- 2.对每一个字符串s进行遍历,comm与s的字符从前向后进行比较,遇到不同的时跳出;
- 3.当公共部分长度为0时,跳出。
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs==null || strs.length==0) return "";
1.暂时存公共前缀
String comm = strs[0];
2.循环队列内的所有 字符串
for (String s:strs) {
int index = 0;
int len = Math.min(comm.length() ,s.length());
3.当满足index<最小长度 且 字符串相同下标处的 字符相同 则 index++
while (index<len && (comm.charAt(index) == s.charAt(index))){index++;}
4.取0~index-1 之内的数据,即为本次公共字符串
comm = comm.substring(0,index);
5.当公共部分为0时,提前跳出
if (comm.length()==0)
return "";
}
6.返回公共前缀
return comm;
}
}
2.344. 反转字符串
- 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
- 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
- 你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
1.解题思路(交换)
- 1.使用swap函数进行前后交换,从两头向中间走。
class Solution {
public void reverseString(char[] s) {
if (s==null || s.length==0 || s.length==1) return;
for (int i = 0; i < s.length/2; i++) {
swap(s,i,s.length-i-1);
}
}
public void swap (char[] chars ,int i,int j){
Character temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
}
3. 557. 反转字符串中的单词 III
- 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
1.解题思路
- 1.先把String以空格为间隔划分为单个字符串数组strs;
- 2.对strs中的每个元素进行反转,同时进行字符串拼接;
- 时间复杂度:O(N)
- 空间复杂度:O(N)
class Solution {
public String reverseWords(String s) {
1.去除特殊情况
if (s==null || s.length()==0 || s.length()==1) return s;
2.按空格划分成字符串数组
String[] strs = s.split(" ");
StringBuilder sb = new StringBuilder();
3.反转的同时进行拼接
for (int i = 0; i < strs.length; i++) {
sb.append(reverseSingle(strs[i]));
sb.append(" ");
}
4.删除最后一个空格!!!!
sb.deleteCharAt(sb.length()-1);
return new String(sb);
}
2.对单个字符串进行反转
public String reverseSingle(String s){
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length/2; i++) {
swap(chars,i,chars.length-1-i);
}
return new String(chars);
}
public void swap (char[] chars ,int i,int j){
Character temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
}
4.3. 无重复字符的最长【子串】
- 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
1.解题思路(滑动窗口解法)
- 1.求的是最长公共子串,而不是子序列;
- 2.滑动窗口法,保证left、right指针之间的字符串是无重复的;
左指针left更新的问题
- left = Math.max(map.get(s.charAt(right))+1,left);
eg:abcddbef
- 1.在发现d重复时,left由0更新为4;
- 2.在发现b重复时,新left取:旧left=4、上一个b下标=1,两者的最大值,即:4。
class Solution {
public int lengthOfLongestSubstring(String s) {
0.排除特殊情况
if(s==null || s.length()==0) return 0;
1.Map存储字符、及其对应下标
Map<Character,Integer> map = new HashMap<>();
2.定义指针left、 最大长度max
int left=0,max=0;
int len = s.length();
3.右指针向后滑动
for (int right = 0; right < len; ++right) {
4.当遇到重复的元素
if (map.containsKey(s.charAt(right))){
5.更新左指针 left
left = Math.max(map.get(s.charAt(right))+1,left);
}
map.put(s.charAt(right),right);
动态获取最大长度max
max = Math.max(max,right-left+1);
}
return max;
}
}
5.无重复字符的最长【子序列】(上一题的子串,改为子序列)
1.解题思路(回溯算法)
class Solution02 {
int resMax;
public int lengthOfLongestSubstring(String s) {
if(s==null || s.length()==0) return 0;
char[] chars = s.toCharArray();
Set<Character> set = new HashSet<>();
resMax = 0;
backTrack(chars,0,set);
return resMax;
}
public void backTrack(char[] chars,int index,Set<Character> set){
先动态更新 子序列最大长度
if (set.size()>resMax){
resMax=set.size();
}
0.终止条件
if (index>= chars.length) return;
1.选择列表
for (int i = 0; i < chars.length; i++) {
1.做选择,只有当前元素不在set里时,才进行回溯
if (set.add(chars[i])){
2.回溯
backTrack(chars, index+1, set);
3.撤销选择
set.remove(chars[i]);
当前元素,已存在于set里时,直接剪枝
}else
return;
}
}
}
6.1143. 最长公共子序列
1.解题思路(动态规划)
- 1.建立二维动态数组dp,存储相同字符的个数
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int t1Len=text1.length();
int t2Len=text2.length();
1.建立二维动态数组,dp[i][j]存储字符串text1前i个元素,与,字符串text2前j个元素,公共的字符个数;
int[][] dp = new int[t1Len+1][t2Len+1];
2.双层for循环遍历
for (int i = 0; i < t1Len; i++) {
for (int j = 0; j < t2Len; j++) {
1.该位置,存在相同的字符时
if (text1.charAt(i)==text2.charAt(j)){
dp[i+1][j+1] = dp[i][j]+1;
2.该位置,字符不同时,取左、上2个位置中较大的1个
}else {
dp[i+1][j+1] = Math.max(dp[i+1][j],dp[i][j+1]);
}
}
}
return dp[t1Len][t2Len];
}
}