当前位置: 首页 > news >正文

Android学习总结之算法篇五(字符串)

字符串求回文字串数目

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));
        }
    }
}    

相关文章:

  • 一条龙网站建设哪家专业百度怎么发布短视频
  • 使用下载的整站asp源代码建设自己的私人网站需要注意哪些成都网络推广优化
  • wordpress 菜单css类宁波seo关键词排名优化
  • 什么直播软件可以看那个东西seo优化首页
  • 个人做网站排版百度搜索引擎优化的养成良好心态
  • 网站的数据库是什么优化疫情防控
  • 什么是接口测试,如何做接口测试?
  • node_modules\deasync: Command failed.
  • cursor机器码重置
  • K8s安全体系全面剖析:从攻击面到最佳实践
  • [创业之路-352]:从创业和公司经营的角度看:分析美国的三大财务报表
  • AI随身翻译设备:从翻译工具到智能生活伴侣
  • SpringBoot+MyBatis Plus+PageHelper+vue+mysql 实现用户信息增删改查功能
  • easy-poi 一对多导出
  • 戴尔笔记本 ubuntu 22.04 开机后进入initramfs界面
  • 网络编程—TCP/IP模型(TCP协议)
  • JSONP跨域访问漏洞
  • #SVA语法滴水穿石# (013)关于 disable iff、matched 、expect 的用法
  • Mysql 数据库下载安装
  • 数字统计题解
  • 【C++奇遇记】C++中的进阶知识(继承(一))
  • Visual FoxPro 6.0学习笔记十五
  • 定制一款国密浏览器(1):Chromium 源码获取和构建
  • 常见前端GET请求以及对应的Spring后端接收接口写法
  • Docker快速安装MongoDB并配置主从同步
  • WiFi加密协议