记录刷力扣时的一些技巧(字符串)
判断str前缀是否为a
str.startsWith(a) ;
切片字符串
str.substring(left,right) ;
分隔
String []arr = str.split(" ") ;
可以替换String.split()的方法
int i = 0 ,j = 0;
int a=0;
while(i < version1.length())
{
a=0;
while(i < version1.length() && version1.charAt(i) != '.')
a = a * 10 + version1.charAt(i++) - '0';
i++;
}
合并
String.jion(" ",strs) ;
哈希表
Map<Character, Integer> map = new HashMap<>();
for (char ch : s.toCharArray()) {
map.put(ch, map.getOrDefault(ch, 0) + 1);
}
排序
箭头前是参数,箭头后是要干什么
ArrayList<Character> list = new ArrayList<>(map.keySet());
list.sort((a,b)->{
//从大到小
return map.get(b)-map.get(a);
}
);
整数转罗马数字
int values[]={1000,900,500,400,100,90,50,40,10,9,5,4,1};
String reps[]={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
StringBuilder res = new StringBuilder();
for(int i=0; i<13; i++){
while(num>=values[i]){
num -= values[i];
res.append(reps[i]);
}
}
return res.toString();
字符串数字相加(各进制通用)
StringBuilder sb = new StringBuilder();
int carry = 0, i = num1.length()-1, j = num2.length()-1;
while(i >= 0 || j >= 0 || carry != 0){
if(i>=0) carry += num1.charAt(i--)-'0';
if(j>=0) carry += num2.charAt(j--)-'0';
sb.append(carry%10);
carry /= 10;
}
return sb.reverse().toString();
如果为链表相加呢?
假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。
给定两个这种链表,请生成代表两个整数相加值的结果链表。
思路:先用栈取值,然后头插法
public ListNode addInList (ListNode head1, ListNode head2) {
// write code here
Stack<Integer> stack1 = new Stack() ;
Stack<Integer> stack2 = new Stack() ;
while(head1 != null){
stack1.push(head1.val) ;
head1 = head1.next ;
}
while(head2 != null){
stack2.push(head2.val) ;
head2 = head2.next ;
}
int carry = 0 ;
ListNode dummy = new ListNode(0) ;
while(!stack1.isEmpty() || !stack2.isEmpty() || carry != 0){
ListNode node = new ListNode(0) ;
if(!stack1.isEmpty()) carry += stack1.pop() ;
if(!stack2.isEmpty()) carry += stack2.pop() ;
node.val = carry%10 ;
carry /= 10 ;
node.next = dummy.next ;
dummy.next = node ;
}
return dummy.next ;
}
kmp算法
def get_next(s):
'''
获取字符串最大的前后缀交集长度列表next
e.g.: s = 'abcabe' -> next = [-1, 0, 0, 0, 1, 2]
*******前后缀名词解释*******
s的前缀为: 'a', 'ab', 'abc', 'abca', 'abcab'
s的后缀为:'bcabe', 'cabe', 'abe', 'be', 'e'
*******生成next列表的规则*******
对s进行遍历的时候,next列表按照如下生成(计算next的值时不看最后一位):
a - next[0] = -1
ab - 无交集 0
abc - 无交集 0
abca - 无交集 0
abcab - 交集 a 1
abcabe - 交集ab 2
'''
# 初始化next列表
l_next = [-1] * len(s)
# 初始化循环指针,j为字符串遍历指针,k为生成next列表的循环指针
j, k = 0, -1
# 遍历字符串s
while j < len(s) - 1:
# 当k未指向字符串时,或者s[j]和s[k]相等时,j和k均往后移动一位
# 然后,next列表next[j]保存k指针指向的位置
if k == -1 or s[j] == s[k]:
j += 1
k += 1
l_next[j] = k # next列表next[j]保存k指针指向的位置
else:
# 这一句是非常关键的,也是最难理解的
# 我也只是大概理解了,还未深入理解
# 如果k已经指向字符串列表,并且s[j]不等于s[k]时
# k指针回溯,意思是将k指向next列表next[k]的位置
# 相当于是指向之前的一次s[j]==s[k]的位置
k = l_next[k]
return l_next
def KMP(s: str, p: str) -> int:
'''
s - 目标字符串;p - 待匹配子串
返回子串在目标字符串中的索引位置
'''
i = j = 0
l_next = get_next(p)
print('next:', l_next)
# 遍历两个字符串
while i < len(s) and j < len(p):
print('*' * 20)
print(' '*i + 'v')
print(s)
print(' '*(i-j) + p)
print(' '*i + '^')
if j == -1 or s[i] == p[j]:
i += 1
j += 1
else:
j = l_next[j]
# 字符串越界保护
if i >= len(s) or j >= len(p): break
# 如果子串p尾部超过了目标字符串,则不用再往后移动比较了
if i-j + len(p) > len(s): return -1
if j == len(p):
return i - j
return -1
if __name__ == '__main__':
s, p = 'abcabcb', 'abcb'
print('=' * 30)
print('return:', KMP(s, p))
判断是不是回文串
public boolean ishuiwen(String s){
int start=0,end=s.length();
while(start<end){
if(s.charAt(start)==s.charAt(end)){start++;end--;}
else return false;
}
return true;
}