diff --git a/Big_data_example/Flink/src/main/java/day05/Example4.java b/Big_data_example/Flink/src/main/java/day05/Example4.java index 05d6842..bd6bc0a 100644 --- a/Big_data_example/Flink/src/main/java/day05/Example4.java +++ b/Big_data_example/Flink/src/main/java/day05/Example4.java @@ -60,7 +60,7 @@ public class Example4 { @Override public void process(String s, Context context, Iterable> iterable, Collector collector) throws Exception { - //初始化一个窗口状态变量,注意:窗口状态变量的可见范围是当前窗口 + //初始化一个窗口状态变量,注意:窗口状态变量的可见范围是当前窗口(无论窗口是否被销毁) ValueState firstCalculate = context.windowState().getState(new ValueStateDescriptor("first", Types.BOOLEAN)); if (firstCalculate.value() == null) { diff --git a/Big_data_example/Flink/src/main/java/day08/Example9.java b/Big_data_example/Flink/src/main/java/day08/Example9.java index 002140c..6167285 100644 --- a/Big_data_example/Flink/src/main/java/day08/Example9.java +++ b/Big_data_example/Flink/src/main/java/day08/Example9.java @@ -83,8 +83,6 @@ public class Example9 { +I[Bob, 2, 1970-01-01T15:00] +I[Mary, 1, 1970-01-01T15:00] +I[liz, 1, 1970-01-01T15:00] - - */ diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T05_LongestPalindrome.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T05_LongestPalindrome.java new file mode 100644 index 0000000..64a7657 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T05_LongestPalindrome.java @@ -0,0 +1,191 @@ +package com.markilue.leecode.hot100; + +import org.junit.Test; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-02-28 10:10 + *@Description: + * TODO 力扣5题 最长回文子串: + * 给你一个字符串 s,找到 s 中最长的回文子串。 + * 如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。 + *@Version: 1.0 + */ +public class T05_LongestPalindrome { + + @Test + public void test() { + String s = "babad"; + System.out.println(longestPalindrome1(s)); + } + + /** + * 思路:最长回文子串,则不能删除,一旦不是回文子串则直接归零 + * TODO DP五部曲: + * 1.dp定义:dp[i][j]表示以j开始以i结尾的子串是不是回文子串 + * 2.dp状态转移方程: + * 1.char[i]==char[j] + * dp[i][j]=dp[i-1][j+1] + * 3.dp初始化: dp[i][i]=true + * 4.dp遍历顺序:从上往下 + * 5.dp举例推导: + * 速度击败51.19% 内存击败7.46% 79ms + * 修改后 62ms + * @param s + * @return + */ + public String longestPalindrome(String s) { + char[] chars = s.toCharArray(); + + boolean[][] dp = new boolean[chars.length][chars.length]; + int maxLength = 0; + int begin = 0; + int end = 0; + + for (int i = 0; i < chars.length; i++) { + for (int j = 0; j <= i; j++) { + if (chars[i] == chars[j]) { + if (i <= j + 1) { + dp[i][j] = true; + } else { + dp[i][j] = dp[i - 1][j + 1]; + } + } + + if (dp[i][j]) { + if (maxLength < i - j + 1) { + maxLength = i - j + 1; + begin = j; + end = i + 1; + } + } + } + } + + return s.substring(begin, end); + + + } + + public boolean isPalindrome(char[] chars, int start, int end) { + + while (start < end) { + if (chars[start++] != chars[end--]) return false; + } + + return true; + + } + + + /** + * 一维dp优化 + * 速度击败54.74% 内存击败77.79% 42ms + * @param s + * @return + */ + public String longestPalindrome1(String s) { + char[] chars = s.toCharArray(); + + boolean[] dp = new boolean[chars.length]; + int maxLength = 0; + int begin = 0; + + for (int i = 0; i < chars.length; i++) { + for (int j = 0; j <= i; j++) { + if (chars[i] == chars[j]) { + if (i <= j + 1) { + dp[j] = true; + } else { + dp[j] = dp[j + 1]; + } + }else { + dp[j]=false; + } + + if (dp[j]&&maxLength < i - j + 1) { + + maxLength = i - j + 1; + begin = j; + + } + } + } + + return s.substring(begin, begin+maxLength); + + + } + + + /** + * 官方最快: + * 分别计算考虑左边;考虑右边;和以i为中心,本质上应该还是O(N^2) + * 速度击败93.2% 内存击败78.66% 7ms + * @param s + * @return + */ + public String longestPalindrome2(String s) { + char[] charStr = s.toCharArray(); + + int maxlen = 0; + int maxStart = 0; + for (int i = 0; i < charStr.length; i++) { + int len = 1; + int left = i - 1; + int right = i + 1; + while (left >= 0 && charStr[i] == charStr[left]) {//查找左边 + len++; + left--; + } + while (right < charStr.length && charStr[i] == charStr[right]) {//查找右边 + len++; + right++; + } + while (left >= 0 && right < charStr.length && charStr[left] == charStr[right]) {//以i为中心 + len += 2; + left--; + right++; + } + if (len > maxlen) { + maxlen = len; + maxStart = left; + } + } + return s.substring(maxStart + 1, maxlen + maxStart + 1); + } + + + /** + * 中心扩展法:看以两个为中心,和以一个为中心是不是回文子串 + * @param s + * @return + */ + public String longestPalindrome3(String s) { + if (s == null || s.length() < 1) { + return ""; + } + int start = 0, end = 0; + for (int i = 0; i < s.length(); i++) { + int len1 = expandAroundCenter(s, i, i); + int len2 = expandAroundCenter(s, i, i + 1); + int len = Math.max(len1, len2); + if (len > end - start) { + start = i - (len - 1) / 2; + end = i + len / 2; + } + } + return s.substring(start, end + 1); + } + + public int expandAroundCenter(String s, int left, int right) { + while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { + --left; + ++right; + } + return right - left - 1; + } + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T06_Convert.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T06_Convert.java new file mode 100644 index 0000000..7868001 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T06_Convert.java @@ -0,0 +1,177 @@ +package com.markilue.leecode.hot100; + +import com.sun.java.swing.plaf.windows.WindowsDesktopIconUI; +import org.junit.Test; + +import java.util.Arrays; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-02-28 11:52 + *@Description: + * TODO 力扣6题 N字形变形: + * 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。 + * 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下: + * P A H N + * A P L S I I G + * Y I R + * 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。 + * 请你实现这个将字符串进行指定行数变换的函数: + * string convert(string s, int numRows); + *@Version: 1.0 + */ +public class T06_Convert { + + @Test + public void test() { +// String s = "ABC"; + String s = "PAYPALISHIRING"; + System.out.println(convert3(s, 3)); + } + + /** + * 思路:先计算一共需要多少列才能记录 + * 速度击败21.1% 内存击败22.88% 26ms + * @param s + * @param numRows + * @return + */ + public String convert(String s, int numRows) { + + //先计算一共需要多少列才能记录 + int length = s.length(); + if (numRows >= length || numRows == 1) return s; + char[] chars1 = s.toCharArray(); + int index = 0; + int col = length / 2; + char[][] chars = new char[numRows][col + 1]; + + for (int k = 0; k < length / (numRows - 1) && index < length; k++) { + int i = 0; + int j = 0; + for (; i < numRows - 1 && index < length; i++) { + chars[i][k * (numRows - 1)] = chars1[index++]; + } + + for (; i > 0 && index < length; i--, j++) { + chars[i][k * (numRows - 1) + j] = chars1[index++]; + } + } + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < chars.length; i++) { + for (int j = 0; j < chars[i].length; j++) { + if (chars[i][j] != '\u0000') + sb.append(chars[i][j]); + } + } + + + return sb.toString(); + + + } + + + /** + * 官方思路:本质上和自己的是一致的,但是判断依据进行了简化 + * 速度击败18.75% 内存击败12.36% 35ms + * @param s + * @param numRows + * @return + */ + public String convert1(String s, int numRows) { + int n = s.length(), r = numRows; + if (r == 1 || r >= n) { + return s; + } + int t = r * 2 - 2; + int c = (n + t - 1) / t * (r - 1); + char[][] mat = new char[r][c]; + for (int i = 0, x = 0, y = 0; i < n; ++i) { + mat[x][y] = s.charAt(i); + if (i % t < r - 1) { + ++x; // 向下移动 + } else { + --x; + ++y; // 向右上移动 + } + } + StringBuffer ans = new StringBuffer(); + for (char[] row : mat) { + for (char ch : row) { + if (ch != 0) { + ans.append(ch); + } + } + } + return ans.toString(); + } + + + /** + * 思路:直接使用stringbuilder进行append + * 速度击败43.99% 内存击败56.51% 8ms + * @param s + * @param numRows + * @return + */ + public String convert2(String s, int numRows) { + int n = s.length(), r = numRows; + if (r == 1 || r >= n) { + return s; + } + StringBuffer[] mat = new StringBuffer[r]; + for (int i = 0; i < r; ++i) { + mat[i] = new StringBuffer(); + } + for (int i = 0, x = 0, t = r * 2 - 2; i < n; ++i) { + mat[x].append(s.charAt(i)); + if (i % t < r - 1) { + ++x; + } else { + --x; + } + } + StringBuffer ans = new StringBuffer(); + for (StringBuffer row : mat) { + ans.append(row); + } + return ans.toString(); + } + + + /** + * 官方直接构造法: + * 把其中的0,1,2,3改成循环的i变量,就是代码。 吐槽一句:这个表格编辑的时候看起来整齐,预览却不整齐,调整了好半天,官方大大能不能优化一下。 + * 0 0+t 0+2t 0+3t + * 1 t-1 1+t 0+2t-1 1+2t 0+3t-1 1+3t + * 2 t-2 2+t 0+2t-2 2+2t 0+3t-2 2+3t + * 3 3+t 3+2t 3+3t + * 好像暂时有错误 + * @param s + * @param numRows + * @return + */ + public String convert3(String s, int numRows) { + int n = s.length(), r = numRows; + if (r == 1 || r >= n) { + return s; + } + StringBuilder sb = new StringBuilder(); + int t = r * 2 - 2; + for (int i = 0; i < r; i++) {// 枚举矩阵的行 + for (int j = 0; j + i < n; j += t) {// 枚举每个周期的起始下标 + sb.append(s.charAt(j + i));// 当前周期的第一个字符 + if (0 < i && i < r - 1 && j + t - i < n) { + sb.append(s.charAt(j + t - 1));// 当前周期的第二个字符 + } + } + } + return sb.toString(); + } + + +}