力扣的算法,这里做个笔记:
一、请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。
[["a","b","c","e"],
["s","f","c","s"],
["a","d","e","e"]]
但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true
示例 2:
输入:board = [["a","b"],["c","d"]], word = "abcd"
输出:false
来源:力扣(LeetCode)
board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]]; word = "ABCCED"
#使用 深度优先搜索(DFS)+ 剪枝 解决
#board: List[List[str]], word: str
class Solution:
def exist(self, board, word) -> bool:
def fes(i, j, k):
if not 0<= i <len(board) or not 0<= j < len(board[0]) or board[i][j]!=word[k]:return False
if k == len(word) -1: return True
tmp, board[i][j] = board[i][j], "/"
res = fes(i+1, j, k+1) or fes(i-1, j, k+1) or fes(i, j+1, k+1) or fes(i, j-1, k+1)
board[i][j] = tmp
return res
for i in range(len(board)):
for j in range(len(board[0])):
if fes(i, j, 0): return True
return False
b = Solution().exist(board, word)
print(b)
二、给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。
示例 1:
输入: "aba"
输出: True
示例 2:
输入: "abca"
输出: True
解释: 你可以删除c字符。
来源:力扣(LeetCode
class Solution {
public boolean validPalindrome(String s) {
int low = 0, height = s.length() - 1;
while (low < height) {
char c1 = s.charAt(low), c2 = s.charAt(height);
if (c1 == c2) {
low++;
height--;
} else {
boolean flag1 = true, flag2 = true;
for (int i = low, j = height - 1; i < j; i++, j--) {
char c3 = s.charAt(i), c4 = s.charAt(j);
if (c3 != c4) {
flag1 = false;
break;
}
}
for (int i = low + 1, j = height; i < j; i++, j--) {
char c3 = s.charAt(i), c4 = s.charAt(j);
if (c3 != c4) {
flag2 = false;
break;
}
}
return flag1 || flag2;
}
}
return true;
}
}
public class validPalindrome {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s = "abc";
Solution sl = new Solution();
boolean b = sl.validPalindrome(s);
System.out.println(b);
}
}
三、给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
s = "abcabcd"
#print(s[1:1])
class Solution(object):
def lengthOfLongestSubstring(self, s):
s = s+"-" #尾部加个字符,处理最长字符在尾部的情况
def lookLike(i,k):
if not 0<= i < len(s)-1 or not 0<= i+k < len(s)-1 or s[i+k] in s[i:i+k]:return k
return lookLike(i,k+1)
max1 = 0
for i in range(len(s)):
v = lookLike(i , 0)
max1 = max(v,max1)
return max1
i = Solution().lengthOfLongestSubstring(s)
print(i)
#还有一种耗时方法
class Solution(object):
def lengthOfLongestSubstring(self, s):
max_len = 0
for i in range(len(s)):
for j in range(i, len(s)):
if j == len(s)-1:
max_len = max(max_len, j+1-i)
break
if s[j+1] in s[i:j+1]:
max_len = max(max_len, j+1-i)
break
return max_len
四、给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
//该方法超时
class Solution1 {
public String longestPalindrome1(String s) {
String s1 = "";
for (int i = 0; i <= s.length() - 1; i++) {
for (int j = s.length() - 1; j >= i; j--) {
char c1 = s.charAt(i), c2 = s.charAt(j);
if (c1 == c2) {
int low = i, hight = j;
while(low <= hight) {
char c3 = s.charAt(low), c4 = s.charAt(hight);
low++;
hight--;
if(c3 != c4) {break;}
if(low >= hight) {
if ((j - i) >= s1.length()) {
s1 = "";
for (int y = i; y <= j; y++) {
s1 = s1 + s.charAt(y);
}
}
}
}
}
}
}
return s1;
}
}
//采用动态规划
class Solution1 {
public String longestPalindrome1(String s) {
String s1 = "";
int n = s.length();
boolean[][] dp = new boolean[n][n];
for (int l = 0; l < n; l++) { // l 代表每次字符串的长度
for (int i = 0; i < n; i++) {
int j = i + l;
if(j>=n) {
break;
}
if (l == 0) {
dp[i][j] = true;
} else if (l == 1) {
dp[i][j] = (s.charAt(i) == s.charAt(j));
} else {
dp[i][j] = (s.charAt(i) == s.charAt(j)) && dp[i + 1][j - 1];
}
if (dp[i][j] && l + 1 > s1.length()) {
s1 = s.substring(i, j+1);
}
}
}
return s1;
}
}
#python 动态规划
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
dp = [[False] * n for _ in range(n)]
ans = ""
# 枚举子串的长度 l+1
for l in range(n):
# 枚举子串的起始位置 i,这样可以通过 j=i+l 得到子串的结束位置
for i in range(n):
j = i + l
if j >= len(s):
break
if l == 0:
dp[i][j] = True
elif l == 1:
dp[i][j] = (s[i] == s[j])
else:
dp[i][j] = (dp[i + 1][j - 1] and s[i] == s[j])
if dp[i][j] and l + 1 > len(ans):
ans = s[i:j+1]
print(ans+"-"+str(i)+"-"+str(j))
return ans
s="cbbabccbaddq"
s1 = Solution().longestPalindrome(s)
print(s1)
//javaScript
var longestPalindrome = function(s) {
if(!s || s.length < 2){
return s;
}
var s_f = s.split('').reverse().join('');
var resultStr = s[0];
var maxLen = 1;
var tmpLen = 1;
var maxStrIndex = 0;
var len = s.length;
//判断字符串是否回文
function isPalinerome(i,r){
if(len - i - 1 == r -tmpLen + 1){
return true
}
return false;
}
//初始化二维数组
var len = s.length;
var arr = new Array(len);
for(var i = 0;i<len;i++){
arr[i] = [];
for(var r = 0;r<len;r++){
arr[i][r] = 0
}
}
for(var i = 0;i<len;i++){
for(var r=0;r<len;r++){
if(s[i] == s_f[r]){
if(i==0 || r==0){
arr[i][r] = 1
}else{
arr[i][r] = arr[i-1][r-1] + 1
tmpLen = arr[i][r]
}
if(tmpLen > maxLen && isPalinerome(i,r)){
maxStrIndex = r;
maxLen = tmpLen;
resultStr = s.substring(i-tmpLen+1,i+1);
}
}
}
}
return resultStr;
};