字符串求回文字串数目
public class CountPalindromicSubstrings {
/**
* 此方法用于计算字符串中回文子串的数量
* @param s 输入的字符串
* @return 回文子串的数量
*/
public static int countSubstrings(String s) {
// 若输入字符串为空或长度为 0,直接返回 0
if (s == null || s.length() == 0) {
return 0;
}
// 用于记录回文子串的数量
int count = 0;
// 获取字符串的长度
int n = s.length();
// 遍历字符串中的每个字符
for (int i = 0; i < n; i++) {
// 以单个字符为中心进行扩展,统计以该字符为中心的回文子串数量
count += expandAroundCenter(s, i, i);
// 以两个相邻字符为中心进行扩展,统计以这两个相邻字符为中心的回文子串数量
count += expandAroundCenter(s, i, i + 1);
}
return count;
}
/**
* 以给定的左右索引为中心向两边扩展,计算以该中心的回文子串数量
* @param s 输入的字符串
* @param left 左索引
* @param right 右索引
* @return 以该中心的回文子串数量
*/
private static int expandAroundCenter(String s, int left, int right) {
// 用于记录以该中心的回文子串数量
int count = 0;
// 当左右索引在字符串范围内,并且对应字符相等时,继续扩展
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
// 每找到一个回文子串,数量加 1
count++;
// 左索引向左移动一位
left--;
// 右索引向右移动一位
right++;
}
return count;
}
public static void main(String[] args) {
// 定义一个示例字符串
String s = "abc";
// 调用 countSubstrings 方法计算回文子串的数量,并输出结果
System.out.println("回文子串的数目是: " + countSubstrings(s));
}
}
环形链表总集
// 定义链表节点类,每个节点包含一个整数值和一个指向下一个节点的引用
class ListNode {
int val;
ListNode next;
// 构造函数,用于初始化节点的值
ListNode(int x) {
val = x;
next = null;
}
}
public class CircularLinkedListAlgorithms {
/**
* 判断链表是否有环
* @param head 链表的头节点
* @return 如果链表有环返回 true,否则返回 false
*/
public static boolean hasCycle(ListNode head) {
// 若链表为空或者只有一个节点,不可能存在环,直接返回 false
if (head == null || head.next == null) {
return false;
}
// 慢指针,每次移动一步
ListNode slow = head;
// 快指针,每次移动两步
ListNode fast = head;
// 当快指针和其下一个节点都不为空时,继续循环
while (fast != null && fast.next != null) {
// 慢指针移动一步
slow = slow.next;
// 快指针移动两步
fast = fast.next.next;
// 如果慢指针和快指针相遇,说明链表存在环
if (slow == fast) {
return true;
}
}
// 快指针到达链表末尾,说明链表不存在环
return false;
}
/**
* 找到环形链表的入环点
* @param head 链表的头节点
* @return 入环点的节点,如果链表无环则返回 null
*/
public static ListNode detectCycle(ListNode head) {
// 若链表为空或者只有一个节点,不可能存在环,直接返回 null
if (head == null || head.next == null) {
return null;
}
// 慢指针,每次移动一步
ListNode slow = head;
// 快指针,每次移动两步
ListNode fast = head;
// 标记链表是否有环
boolean hasCycle = false;
// 当快指针和其下一个节点都不为空时,继续循环
while (fast != null && fast.next != null) {
// 慢指针移动一步
slow = slow.next;
// 快指针移动两步
fast = fast.next.next;
// 如果慢指针和快指针相遇,说明链表存在环
if (slow == fast) {
hasCycle = true;
break;
}
}
// 如果链表无环,返回 null
if (!hasCycle) {
return null;
}
// 慢指针重新指向头节点
slow = head;
// 慢指针和快指针同时移动一步,直到它们相遇,相遇点即为入环点
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
/**
* 计算环形链表的环长度
* @param head 链表的头节点
* @return 环的长度,如果链表无环则返回 0
*/
public static int cycleLength(ListNode head) {
// 若链表为空或者只有一个节点,不可能存在环,直接返回 0
if (head == null || head.next == null) {
return 0;
}
// 慢指针,每次移动一步
ListNode slow = head;
// 快指针,每次移动两步
ListNode fast = head;
// 标记链表是否有环
boolean hasCycle = false;
// 当快指针和其下一个节点都不为空时,继续循环
while (fast != null && fast.next != null) {
// 慢指针移动一步
slow = slow.next;
// 快指针移动两步
fast = fast.next.next;
// 如果慢指针和快指针相遇,说明链表存在环
if (slow == fast) {
hasCycle = true;
break;
}
}
// 如果链表无环,返回 0
if (!hasCycle) {
return 0;
}
// 初始化环的长度为 1
int length = 1;
// 快指针移动一步
fast = fast.next;
// 快指针继续移动,直到再次和慢指针相遇,记录移动的步数
while (slow != fast) {
fast = fast.next;
length++;
}
return length;
}
public static void main(String[] args) {
// 构建一个有环的链表示例
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node2; // 形成环
// 调用 hasCycle 方法判断链表是否有环并输出结果
System.out.println("链表是否有环: " + hasCycle(node1));
// 调用 detectCycle 方法找到入环点
ListNode entryPoint = detectCycle(node1);
if (entryPoint != null) {
// 若有入环点,输出入环点的值
System.out.println("入环点的值: " + entryPoint.val);
} else {
// 若没有入环点,输出提示信息
System.out.println("没有入环点");
}
// 调用 cycleLength 方法计算环的长度并输出结果
System.out.println("环的长度: " + cycleLength(node1));
}
}
有序数组去重
public class RemoveDuplicatesSortedArray {
/**
* 此方法用于移除有序数组中的重复元素,使每个元素只出现一次。
* 并返回移除重复元素后数组的新长度。
* 原数组会被修改,新长度之前的元素为去重后的元素。
*
* @param nums 输入的有序整数数组
* @return 去重后数组的新长度
*/
public static int removeDuplicates(int[] nums) {
// 如果数组为空,直接返回 0
if (nums == null || nums.length == 0) {
return 0;
}
// 慢指针,指向去重后数组的最后一个位置
int slow = 0;
// 快指针,用于遍历数组
for (int fast = 1; fast < nums.length; fast++) {
// 如果快指针指向的元素和慢指针指向的元素不相等
if (nums[fast] != nums[slow]) {
// 慢指针向后移动一位
slow++;
// 将快指针指向的元素赋值给慢指针当前位置
nums[slow] = nums[fast];
}
}
// 慢指针的位置加 1 就是去重后数组的长度
return slow + 1;
}
public static void main(String[] args) {
// 定义一个有序数组
int[] nums = {1, 1, 2, 2, 3, 4, 4, 4, 5};
// 调用 removeDuplicates 方法进行去重
int newLength = removeDuplicates(nums);
System.out.println("去重后数组的新长度: " + newLength);
System.out.print("去重后的数组元素: ");
for (int i = 0; i < newLength; i++) {
System.out.print(nums[i] + " ");
}
}
}
数组合并区间
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class MergeIntervals {
/**
* 合并重叠的区间
* @param intervals 输入的区间数组
* @return 合并后不重叠的区间数组
*/
public static int[][] merge(int[][] intervals) {
// 如果输入数组为空或者长度为 0,直接返回空数组
if (intervals == null || intervals.length == 0) {
return new int[0][0];
}
// 按照区间的起始位置进行排序
Arrays.sort(intervals, Comparator.comparingInt(a -> a[0]));
// 用于存储合并后的区间
List<int[]> merged = new ArrayList<>();
// 取第一个区间作为初始的合并区间
int[] current = intervals[0];
// 遍历剩余的区间
for (int i = 1; i < intervals.length; i++) {
int[] interval = intervals[i];
// 如果当前区间的结束位置大于等于下一个区间的起始位置,说明有重叠
if (current[1] >= interval[0]) {
// 更新当前区间的结束位置为两个区间结束位置的最大值
current[1] = Math.max(current[1], interval[1]);
} else {
// 没有重叠,将当前区间加入到合并列表中
merged.add(current);
// 更新当前区间为下一个区间
current = interval;
}
}
// 将最后一个合并的区间加入到列表中
merged.add(current);
// 将列表转换为二维数组并返回
return merged.toArray(new int[merged.size()][]);
}
public static void main(String[] args) {
int[][] intervals = {{1, 3}, {2, 6}, {8, 10}, {15, 18}};
int[][] mergedIntervals = merge(intervals);
// 输出合并后的区间
for (int[] interval : mergedIntervals) {
System.out.println(Arrays.toString(interval));
}
}
}