发这类的博客只是是记录一下回顾算法的过程
//最大正方形
//思路: 动态规划,定义dp[][],其中dp[i][j]表示以(i, j)为右下角坐标的最大正方形边长,由此可得关系式如下
//dp[i][j] = min(dp[i - 1][j], dp[i- 1][j - 1], dp[i][j - 1]) + 1
public int maximalSquare(char[][] matrix) {
int maxSide = 0;
if (matrix == null || matrix.length == 0) {
return maxSide;
}
int rows = matrix.length, columns = matrix[0].length;
int[][] dp = new int[rows][columns];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (matrix[i][j] == '1') {
if (i == 0 || j == 0) {
dp[i][j] = 1;
} else {
dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
}
maxSide = Math.max(maxSide, dp[i][j]);
}
}
}
return maxSide * maxSide;
}
//数组中的第K大元素
//思路: 利用大根堆,将数组构造成一棵大根堆二叉树,然后删除根节点再次构造大根堆,重复操作k - 1次即可得到第K大的元素
public int findKthLargest(int[] nums, int k) {
if (nums == null || nums.length == 0) {
return -1;
}
for (int i = nums.length - 1; i >= 0; i--) {
heapify(nums, i, nums.length);
}
int heapSize = nums.length;
for (int i = nums.length - 1; i >= nums.length - k + 1; i--) {
swap(nums, 0, i);
heapSize--;
heapify(nums, 0, heapSize);
}
return nums[0];
}
public void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
public void heapify(int[] nums, int index, int heapSize) {
int left = index * 2 + 1;
while (left < heapSize) {
int largest = left + 1 < heapSize && nums[left + 1] > nums[left] ? left + 1 : left;
if (nums[index] > nums[largest]) {
break;
} else {
swap(nums, index, largest);
index = largest;
left = index * 2 + 1;
}
}
}
//反转链表
//思路: 定义三个指针p, q, temp,分别交替指向对方达到翻转链表
public ListNode reverseList2(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode temp = null;
ListNode p = head, q = head.next;
while (q != null) {
p.next = temp;
temp = p;
p = q;
q = q.next;
}
p.next = temp;
return p;
}
//回文子串
//思路: 中心扩散法则,由于字符串长度有奇偶,所以中心点分为单个字符、两个字符为中心
//确认好中心点之后就往两边扩散以此来计算回文出现的次数
public int countSubstrings(String s) {
//获取字符串长度
int len = s.length();
int ans = len;
//以单个字符为中心点
for (int i = 0; i < len; i++) {
int left = i - 1;
int right = i + 1;
while (left >= 0 && right < len && s.charAt(left) == s.charAt(right)) {
left--;
ans++;
right++;
}
}
//以两个字符为中心点
for (int i = 0; i < len - 1; i++) {
int left = i;
int right = i + 1;
while (left >= 0 && right < len && s.charAt(left) == s.charAt(right)) {
left--;
ans++;
right++;
}
}
return ans;
}
//最长连续序列
//思路: 把所有元素存储到HashSet中,然后遍历Set寻找可以作为连续序列的开头元素x,即HashSet中
//不存在元素x - 1, 不存在则继续寻找x + 1, 存在则跳过, 维护几个变量来记录最长连续序列的长度
public int longestConsecutive(int[] nums) {
Set<Integer> hashSet = new HashSet<>();
for (int num : nums) {
hashSet.add(num);
}
int maxLength = 0;
for (int num : nums) {
if (!hashSet.contains(num)) {
int currentNum = num;
int currentLength = 1;
while (hashSet.contains(currentNum + 1)) {
currentNum += 1;
currentLength++;
}
maxLength = Math.max(currentLength, maxLength);
}
}
return maxLength;
}