13、罗马数字转整数
要点:字符串、HashMap
解题思路
将字符从左至右遍历(charAt(i)方法),如果下一个位置的值比当前位置的值大,就减去当前位置的值,反之,加上当前位置的值
HashMap
HashMap<key类型,value类型> map名=new HashMap<key类型,value类型>()
> {{
> put(key值,value值);
> }}; //双括号,结尾分号,类型不能使用基本数据类型,要使用封装后的类
常用的封装类:boolean-Boolean、char-Character、byte-Byte、int-Integer
字符串
14、最长公共前缀
要点:字符串配对、最长前缀
解题思路
先将首个字符串strs[0]置为最长公共子串,再遍历字符串数组,如不符合就将字串长度减一,再遍历,循环到有符合的数据为止
使用String中的startswith()和substring()方法
String方法总结
public String longestCommonPrefix(String[] strs) {
if(strs.length==0)
return "";
//公共前缀比所有字符串都短,随便选一个先
String s=strs[0];
for (String string : strs) {
while(!string.startsWith(s)){
if(s.length()==0)return "";
//公共前缀不匹配就让它变短!
s=s.substring(0,s.length()-1);
}
}
return s;
}
20、有效的括号
要点:String类、栈
解题思路
1、字符串中第一次遇到的右括号,必须与它左边最近的左括号配对。遍历字符串,如果是左括号,就将它对应的右括号入栈,当遍历到右括号时,判断它是否与栈顶元素相等。
class Solution {
public boolean isValid(String s) {
//栈
Stack <Character> stack=new Stack<Character>();
int i=0,len=s.length();
for(;i<len;i++){
char c=s.charAt(i);
if(c=='('){
stack.push(')');
}
else if(c=='['){
stack.push(']');
}
else if(c=='{'){
stack.push('}');
}
else if(stack.isEmpty() || stack.pop()!=c)
return false;
}
return stack.isEmpty();
}
}
2、看到大佬的一个方法,用String类中的contains方法,遇到配对的括号就将其替换为’’,一直循环遍历,直到字符串中不含配对的括号,此时再判断字符串长度。
简单粗暴,string类中的方法太多,记不住啊
```java
class Solution {
public boolean isValid(String s) {
while(s.contains("()")||s.contains("[]")||s.contains("{}")){
if(s.contains("()")){
s=s.replace("()","");
}
if(s.contains("{}")){
s=s.replace("{}","");
}
if(s.contains("[]")){
s=s.replace("[]","");
}
}
return s.length()==0;
}
}
21、合并两个有序链表
要点:链表
解题思路
1、非递归。新开辟一个空间用来存放最后的结果。当待合并的链表都不为空时,将符合条件的链表添加到新定义的链表后面。
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode temp=new ListNode(0);
ListNode f=temp;
if(l1==null) return l2;
if(l2==null) return l1;
while(l1!=null && l2!=null){
if(l2.val>=l1.val){
//插入到l1
f.next=l1;
f=f.next;
l1=l1.next;
}
else{
f.next=l2;
f=f.next;
l2=l2.next;
}
}
if(l1==null){
f.next=l2;
}
else{
f.next=l1;
}
return temp.next;
2、递归。做递归处理时,先明确跳出递归的边界和循环的内容。此题中递归结束的边界为待排序的链表为空,循环的内容是将符合条件的待排链表链接到另一个链表后面
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode temp=new ListNode(0);
ListNode f=temp;
//递归
if(l1==null) return l2;
if(l2==null) return l1;
if(l1.val<=l2.val){
l1.next=mergeTwoLists(l1.next,l2);
return l1;
}
else{
l2.next=mergeTwoLists(l1,l2.next);
return l2;
}
}
26、删除有序数组中的重复项
要点:双指针
解题思路
双指针:用一个指针slow指向满足条件的元素待插入的位置,另一个指针fast指向要遍历的元素。
public int removeDuplicates(int[] nums) {
//双指针
int low = 0;
for(int fast=0;fast<nums.length;fast++){
if(nums[low] != nums[fast]){
nums[low+1] = nums[fast];
low++;
}
}
return low+1;
}
扩展:如果没有原地修改的限制,可以使用hash表,将数组的值作为hash表的key值,当有重复时,会自动覆盖,更为简洁
public class removeDuplicates {
//删除重复项
public static void main(String[] args) {
int nums[] = {1,1,2};
HashMap<Integer,Integer > map_a=new HashMap<Integer,Integer>();
int len=nums.length;
for(int i=0;i<len;i++){
//将数组的值做为hash表的key
map_a.put(nums[i], 1);
}
System.out.println(map_a.keySet());
}
}
27、移除元素
与26思路一致
public int removeElement(int[] nums, int val) {
int low=0,fast=0;
for(;fast<nums.length;fast++){
if(nums[fast]!=val){
nums[low]=nums[fast];
low++;
}
}
return low;
}
35、搜素插入图片
要点:二分查找
解题思路
1、暴力循环查找,时间复杂度不符合题意,但代码简单易理解
public int searchInsert(int[] nums, int target) {
for(int i=0;i<nums.length;i++){
if(nums[i]>=target){
if(i==0)
return 0;
else
return i;
}
}
return nums.length;
}
2、二分查找,时间复杂度符合题意。
public int searchInsert(int[] nums, int target) {
int low=0,high=nums.length-1;
int flag=0,len=high;
while(low<=high){ //循环边界
flag=(low+high)/2;
if(nums[flag]==target){
return flag; //在数组中的位置
}
else if(nums[flag]>target){
high=flag-1;
}
else if(nums[flag]<target){
low=flag+1;
}
else
return flag;
}
//low>high时,序列中没有指定的目标值,此时可能存在以下几种情况
//1.目标值比第一个元素小,应插入在0号位置
//2.目标值比最后一个元素大,应插入在nums.length号位置
//3.目标值插入在数组中间某一个位置
//此时,high号位置存放的数是最大的比目标值小的数,所以应该返回high+1
return high+1;
}