算法记录 两数之和(双层for循环数组操作) 两个单链求和问题(两个变量引用同一个单链对象) 整数反转(整数反转算法) 回文数(也可采用整数反转算法来判断) 罗马数字转整数(map或switch的算法) 最长公共前缀 有效的括号(栈思想:校验括号闭合) 合并两个有序单链(递归思想) 两数之和(双层for循环数组操作) LeetCode: 1.两数之和
class Solution { public int[] twoSum(int[] nums, int target) { for(int i = 0; i < nums.length -1; i++){ for(int j = i+1; j < nums.length; j++){ if(nums[i]+nums[j]==target){ return new int[]{i,j}; } } } return new int[0]; } }
1 2 3 4 5 6 7 8 9 10 11 12 两个单链求和问题(两个变量引用同一个单链对象) LeetCode: 2.两数相加
/**
- Definition for singly-linked list.
- public class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
- }
*/ class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode head = new ListNode(0); ListNode curr = head; //单链的精髓就在这里:curr和head引用的是同一个对象 //所以我们使用head进行最后的输出, 使用curr进行操作 int carry = 0;//进位值 while(l1!=null || l2!=null){ //获取当前node的值 int v1 = l1!=null?l1.val:0; int v2 = l2!=null?l2.val:0; //相加操作,记得加上一个节点的进位 int sum = v1 + v2 + carry; //进位值需要带到下个节点 carry = sum / 10; //int类型会自动屏除小数点后的,如果小于10去/10则进位变成了0 //将和的余数放入ListNode curr.next=new ListNode(sum%10); curr=curr.next; if(l1!=null) l1 = l1.next; if(l2!=null) l2 = l2.next; } if(carry > 0){//如果还存在进位值 curr.next = new ListNode(carry); } return head.next; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 整数反转(整数反转算法) LeetCode: 7.整数反转
class Solution { public int reverse(int x) { int rev = 0; while (x != 0) { if (rev < Integer.MIN_VALUE / 10 || rev > Integer.MAX_VALUE / 10) { return 0; } //除余10取零头个位数 int digit = x % 10; //上一个结果乘以10加上现在这个个位数 rev = rev * 10 + digit; //除以10取整去除取过的个位 x /= 10; //再通过循环进行整数的反转 } return rev; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 回文数(也可采用整数反转算法来判断) LeetCode: 9.回文数 也采用整数反转的思路来做,把上面的整数反转公式简化如下
result = result * 10 + x % 10; x /= 10; 1 2 class Solution { public boolean isPalindrome(int x) { if(x < 0){//负数肯定都不是回文,直接返回false return false; } int org = x; int result = 0; while(x != 0){ //进行整数反转操作 result = result * 10 + x % 10; x /= 10; } if(result == org){ return true; }else{ return false; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 罗马数字转整数(map或switch的算法) LeetCode: 13.罗马数字转整数 规律:左边比右边小的则是减法, 其他加法
class Solution { private int getValue(char c){ switch(c) { case 'I': return 1; case 'V': return 5; case 'X': return 10; case 'L': return 50; case 'C': return 100; case 'D': return 500; case 'M': return 1000; default : return 0; } } public int romanToInt(String s) { int value = 0; for(int i = 0; i < s.length(); i++){ if(i < (s.length() - 1 ) && getValue(s.charAt(i)) < getValue(s.charAt(i+1))){ value -= getValue(s.charAt(i)); }else{ value += getValue(s.charAt(i)); } } return value; } }
上面这种switch匹配的效率更高,下面的map查找效率较慢
class Solution { Map<Character,Integer> map = new HashMap<Character,Integer>(){{ put('I',1); put('V',5); put('X',10); put('L',50); put('C',100); put('D',500); put('M',1000); }}; public int romanToInt(String s) { int value = 0; for(int i = 0; i < s.length(); i++){ if(i < (s.length() - 1 ) && map.get(s.charAt(i)) < map.get(s.charAt(i+1))){ value -= map.get(s.charAt(i)); }else{ value += map.get(s.charAt(i)); } } return value; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 最长公共前缀 LeetCode: 14.最长公共前缀 我这个解题思路不是官方的,但是比较简单好理解,采用的是指针的思维
class Solution { public String longestCommonPrefix(String[] strs) { //建立一个公共指针,比对各元素同一指针下的字符是否相同 //不相同则返回指针,相同指针就继续右移 int index = 0; while(true){//外层循环控制指针 boolean ct = true;//控制外层循环是否继续 char pre = '\u0000'; //声明当前指针对应的字符(一开始是默认空\u0000) for(String str : strs){//遍历数组 if("".equals(str)) return "";//有元素为空,则直接返回空字符串 if(index >= str.length()){ct = false; break;}//指针到达数组长度,则停止遍历并通知外层指针停止移动 if('\u0000' == pre) pre = str.charAt(index);//(初始化比对字符)录入第一个字符串的当前指针对应字符,用于后面的字符串比对 if(pre != str.charAt(index)) {ct = false; break;}//发现同一指针下有不相同的字符则停止遍历并通知外层循环停止移动指针 } if(!ct) break; index++;//指针加一 } String strRes = strs[0];//随便取出一个字符串 if(strRes!=null){ return strRes.substring(0,index); }else{ return ""; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 有效的括号(栈思想:校验括号闭合) LeetCode: 20.有效的括号 给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。
class Solution { Map<Character,Character> map = new HashMap<>(){{ put(')','('); put('}','{'); put(']','['); }}; public boolean isValid(String s) { int length = s.length(); if(1 == length%2){//奇数肯定没有闭合 return false; } Stack stack = new Stack(); for(int i = 0; i < s.length(); i++){ if('('==s.charAt(i) || '{'==s.charAt(i)|| '['==s.charAt(i)){ //左括号就push进去 stack.push(s.charAt(i)); }else{ //右括号则先判断stack里还能不能弹 if(!stack.isEmpty()){ //弹出来的左括号和map对应的左括号比对,不一样说明未按正确顺序闭合 Character c = stack.pop(); if(c != map.get(s.charAt(i))){ return false; } }else{ return false; } } } return stack.isEmpty(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 合并两个有序单链(递归思想) LeetCode: 21.合并两个有序单链 两个有序单链合并成一个有序单链
方法一: 递归思想
递归函数必须要有终止条件,否则会出错; 递归函数先不断调用自身,直到遇到终止条件后进行回溯,最终返回答案。 根据以上规律考虑本题目:
终止条件:当两个链表都为空时,表示我们对链表已合并完成。 如何递归:我们判断 l1 和 l2 头结点哪个更小,然后较小结点的 next 指针指向其余结点的合并结果。(调用递归) 宗旨:谁小返回谁,然后继续操作小的next,调用自身方法,去和大的再比对
**
- Definition for singly-linked list.
- public class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
- }
*/ class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { //宗旨,谁小返回谁,然后继续操作小的next,调用自身方法,去和大的再比对 if(l2 == null){ return l1; }else if(l1 == null){ return l2; }else if(l1.val < l2.val){ l1.next = mergeTwoLists(l1.next,l2); return l1; }else{ l2.next = mergeTwoLists(l1, l2.next); return l2; } } }