java算法day8

    1. 实现 strStr()
  • 459.重复的子字符串

实现strStr()

可以说是暴力解。但是里面的处理比一开始自己写的冗余逻辑要好

class Solution {
    public int strStr(String haystack, String needle) {
        char[] strh = haystack.toCharArray();
        char[] strn = needle.toCharArray();
        //优化1.没必要全部扫描完。因为最后一部分如果没有子串长那没有比较的意义,所以用字符串的长度减子串的长度。
        //模拟:abcdef , cde
        //这里取不取等是要自己算一下的。上例看来,i=3是有意义的,所以取等
        for (int i = 0; i <= strh.length - strn.length; i++) {
            int j = 0;
            //这个条件优化,就是我当时没想到的一个思维,我直接在i的基础上开始用j逐渐+1就可以了。并且两个字符串比较的过程我也包含在里面。这里用while比用if更省事,这是我一开始也没想到的。
            while (j < strn.length && i + j < strh.length && strh[i + j] == strn[j]) {
                j++;
            }
            //如果这里判断通过了,说明找到子串了。
            if (j == strn.length) {
                return i;
            }
        }
        return -1;
    }
}

重复的子字符串

首先题意是:给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。
思路:看到这个话要这么想,如果一个字符串s包含一个重复的字串,那么说明我可以多次移位和换行该字符串,并使其与原始字符串匹配。一定要这么想,如果你想去挨个的枚举扫一遍,那我只能说是麻烦中的麻烦。
比如abcabc
移位一次cabcab
移位两次bcabca
移位三次abcabc
这就是发现的规律。
但是存在一个问题,这个移动的次数存在不确定。而且每次移动都要进行匹配是否是相同字符串,这里又有一部分开销。
所以有没有什么方法,能够把这些开销降下来。回答是有的,这也是这个题的解法。
解法
1.创建一个新的字符串,str。将s与自身拼接。即str=s+s。
2.然后从str中去掉第一个和最后一个字符,得到str.substring(1,str.length()-1)
3.最后,检查这个新的字符串是否包含原始的s。

核心思想
如果 s 由重复的子串构成,那么在 s + s 中,去掉首尾字符后,一定还能找到一个完整的 s
为什么这个方法有效?
如果 s 是由重复子串构成的,那么在 s + s 中,原来的 s 会出现至少两次(除了首尾各少一个字符的情况)。
去掉首尾字符后,如果原来的模式是重复的,那么仍然会保留至少一个完整的 s
如果 s 不是由重复子串构成的,那么在去掉首尾字符后的字符串中,就不可能找到一个完整的 s

时间和空间都是o(n)。与kmp时间量级是相同的,但是kmp效率要更高一点,因为他更简洁。

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        String str = s + s;
        return str.substring(1,str.length()-1).contains(s);
    }
}
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
日期计算在Java中通常使用java.util.Calendar类进行实现。通过该类,可以计算两个日期之间的天数、月数、年数等。下面是一些基本的日期计算方法: 1. 计算两个日期之间的天数 ```java Calendar cal1 = Calendar.getInstance(); cal1.set(2019, 8, 1); Calendar cal2 = Calendar.getInstance(); cal2.set(2019, 8, 10); long diff = cal2.getTimeInMillis() - cal1.getTimeInMillis(); long days = diff / (24 * 60 * 60 * 1000); System.out.println("Days between two dates: " + days); ``` 2. 计算两个日期之间的月数 ```java Calendar cal1 = Calendar.getInstance(); cal1.set(2019, 8, 1); Calendar cal2 = Calendar.getInstance(); cal2.set(2020, 3, 10); int months = (cal2.get(Calendar.YEAR) - cal1.get(Calendar.YEAR)) * 12 + cal2.get(Calendar.MONTH) - cal1.get(Calendar.MONTH); System.out.println("Months between two dates: " + months); ``` 3. 计算两个日期之间的年数 ```java Calendar cal1 = Calendar.getInstance(); cal1.set(2019, 8, 1); Calendar cal2 = Calendar.getInstance(); cal2.set(2021, 8, 1); int years = cal2.get(Calendar.YEAR) - cal1.get(Calendar.YEAR); System.out.println("Years between two dates: " + years); ``` 4. 计算某个日期加上一定天数后的日期 ```java Calendar cal = Calendar.getInstance(); cal.set(2019, 8, 1); int daysToAdd = 10; cal.add(Calendar.DAY_OF_MONTH, daysToAdd); Date newDate = cal.getTime(); System.out.println("New date: " + newDate); ``` 5. 计算某个日期减去一定天数后的日期 ```java Calendar cal = Calendar.getInstance(); cal.set(2019, 8, 11); int daysToSubtract = 10; cal.add(Calendar.DAY_OF_MONTH, -daysToSubtract); Date newDate = cal.getTime(); System.out.println("New date: " + newDate); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值