简单算法2
二分查找
package com.sly.uploadfile.algorithm.pack1; import java.util.Arrays; /** * Created by fmgao on 2019/9/25. * <p> * Java语言二分查找代码实现 */ public class ErFenChaZhao { /** * 二分查找key值对应的下标 * * @param source 输入的源数组 ,请保证为一个有序数组 * @param key 需要查找的值 * @return 正数为查找到的坐标,-1表示没有查到 */ public static int binarySearch(int[] source, int key) { int low = 0; int high = source.length - 1; while (low <= high) { int mid = (low + high) >>> 1; //使用位移运算法高效地获取折中下标,这里不考虑符号,所以使用>>> int midVal = source[mid]; if (midVal < key) { low = mid + 1; } else if (midVal > key) { high = mid - 1; } else return mid; } return -1; } public static void main(String[] args) { int[] source = new int[]{12, 213, 232, 343, 123, -1, 123, 232424, 1253, 56, 456, 234, -2342}; //保证数组为有序数组 Arrays.sort(source); //打印排序后的数组元素 System.out.print("Sorted Source : "); for (int i = 0; i < source.length; i++) { System.out.print(source[i] + " "); } System.out.println(); System.out.println(binarySearch(source, 56)); } }
俩数相加
package com.sly.uploadfile.algorithm.twoadd; /** * Created by fmgao on 2019/11/13. * <p> * 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的, * 并且它们的每个节点只能存储 一位 数字。 * <p> * 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 * <p> * 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。 * <p> * 示例: * <p> * 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) * 输出:7 -> 0 -> 8 * 原因:342 + 465 = 807 */ public class TwoAdd { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode dumpHead = new ListNode(0); ListNode p = l1, q = l2, curr = dumpHead; int carry = 0; while (p != null || q != null) { int x = (p != null) ? p.data : 0; int y = (q != null) ? q.data : 0; int sum = x + y + carry; carry = sum / 10; curr.next = new ListNode(sum % 10); curr = curr.next; if (p != null) p = p.next; if (q != null) q = q.next; } if (carry != 0) { curr.next = new ListNode(carry); } return dumpHead.next; } public static void main(String[] args) { SingleLinkedList l1 = new SingleLinkedList(); l1.addData(1); l1.addData(2); l1.addData(5); SingleLinkedList l2 = new SingleLinkedList(); l2.addData(3); l2.addData(2); l2.addData(7); TwoAdd solution = new TwoAdd(); ListNode l3 = solution.addTwoNumbers(l1.head, l2.head); while (l3 != null) { if (l3.next == null) { System.out.print(l3.data); l3 = l3.next; } else { System.out.print(l3.data + "->"); l3 = l3.next; } } System.out.println(); System.out.println("/:" + 25 / 10); System.out.println("%:" + 25 % 10); } }
俩数相加
package com.sly.uploadfile.algorithm.twoadd; import java.util.HashMap; import java.util.Map; /** * Created by fmgao on 2019/12/30. */ public class TwoNum { public static void main(String[] args) { int[] nums = {2, 7, 11, 15}; int tar = 22; int[] ints = twoNum(nums, tar); for (int s : ints) { System.out.println(s); } } public static int[] twoNum(int[] nums, int target) { Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int com = target - nums[i]; if (map.containsKey(com)) { return new int[]{map.get(com), i}; } else { map.put(nums[i], i); } } throw new IllegalArgumentException("No two sum solution"); } }
是否有重复元素
package com.sly.uploadfile.algorithm; import java.util.HashMap; import java.util.Map; /** * Created by fmgao on 2019/9/27. * <p> * [Leetcode] 220. 存在重复元素 II java * <p> * 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j, * 使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ。 * <p> * Example 1: * <p> * Input: nums = [1,2,3,1], k = 3, t = 0 * Output: true * <p> * Example 2: * <p> * Input: nums = [1,0,1,1], k = 1, t = 2 * Output: true * <p> * Example 3: * <p> * Input: nums = [1,5,9,1,5,9], k = 2, t = 3 * Output: false */ public class ContainsNearByDuplicate { public static void main(String[] args) { int[] nu = {1, 2, 3, 1}; boolean b = containsNearByAlmostDuplicate(nu, 21, 1); System.out.println(b); } public static boolean containsNearByAlmostDuplicate(int[] a, int k, int t) { // if (k < 1 || t < 0 || nums == null || nums.length < 2) { // return false; // } // SortedSet<Long> set = new TreeSet<>(); // for (int j = 0; j < nums.length; j++) { // SortedSet<Long> subset = set.subSet((long) nums[j] - t, (long) nums[j] + t + 1); // if (!subset.isEmpty()) { // return true; // } // if (j >= k) { // set.remove((long) nums[j - k]); // } // set.add((long) nums[j]); // } // for (Long ss : set) { // System.out.println(ss); // } /** * 给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的绝对值最大为 k。 示例 1: 输入: nums = [1,2,3,1], k = 3 输出: true 示例 2: 输入: nums = [1,0,1,1], k = 1 输出: true 示例 3: 输入: nums = [1,2,3,1,2,3], k = 2 输出: false */ // (双指针法,快慢指针加了一个限定(Math.abs ( i-j )<=k),相当于滑动窗口(有滑动限定))+map存储元素 int j; Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < a.length; i++) { // 当map中存在数组元素时,证明两个元素相同 if (map.containsKey(a[i])) { // 让j等于map中与数组元素相等的那个键对应值 j = map.get(a[i]); // 判断新的这个(遍历后的)索引和Map中的索引的差是否小于k,小于则输出true。 if (Math.abs(i - j) <= k) { System.out.println("true"); } //将新的索引值添加到map中 map.put(a[i], i); } else { // 向map中添加元素 map.put(a[i], i); } } System.out.println("false"); return false; } }
数字1的个数
package com.sly.uploadfile.algorithm;
/**
* Created by fmgao on 2019/9/29.
* <p>
* [LeetCode] Number of Digit One 数字1的个数
* Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.
* For example:
* Given n = 13,
* Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.
*/
/**
《编程之美》上这样说:
设N = abcde ,其中abcde分别为十进制中各位上的数字。
如果要计算百位上1出现的次数,它要受到3方面的影响:百位上的数字,百位以下(低位)的数字,百位以上(高位)的数字。
如果百位上数字为0,百位上可能出现1的次数由更高位决定。比如:12013,
则可以知道百位出现1的情况可能是:100~199,1100~1199,2100~2199,,...,11100~11199,一共1200个。
可以看出是由更高位数字(12)决定,并且等于更高位数字(12)乘以 当前位数(100)。注意:高位数字不包括当前位
如果百位上数字为1,百位上可能出现1的次数不仅受更高位影响还受低位影响。比如:12113,
则可以知道百位受高位影响出现的情况是:100~199,1100~1199,2100~2199,,....,11100~11199,一共1200个。
和上面情况一样,并且等于更高位数字(12)乘以 当前位数(100)。
但同时它还受低位影响,百位出现1的情况是:12100~12113,一共14个,等于低位数字(13)+1。 注意:低位数字不包括当前数字
如果百位上数字大于1(2~9),则百位上出现1的情况仅由更高位决定,比如12213,
则百位出现1的情况是:100~199,1100~1199,2100~2199,...,11100~11199,12100~12199,一共有1300个,
并且等于更高位数字+1(12+1)乘以当前位数(100)
*/
public class CountDigitOne {
public static void main(String[] args) {
int a = 27;
int i = countDigitOne(a);
System.out.println(i);
}
public static int countDigitOne(int n) {
if (n < 1) {
return 0;
}
int res = 0;
long i = 1;
while (n >= i) {
res += (n / i + 8) / 10 * i + ((n / i) % 10 == 1 ? (n % i + 1) : 0);
i *= 10;
}
return res;
}
}
package com.sly.uploadfile.algorithm;
/**
* Created by fmgao on 2019/9/29.
*/
public class CountDigitOne2 {
public static void main(String[] args) {
int a = 27;
int i = countDigitOne(a);
System.out.println(i);
}
public static int countDigitOne(int n) {
if (n <= 0) {
return 0;
}
String stringN = n + "";
int ans = 0;
while (!stringN.isEmpty()) {
int tempLen = stringN.length();
String firstChar = stringN.charAt(0) + "";
if (Integer.parseInt(firstChar) >= 2) {
ans += 1 * Math.pow(10, tempLen - 1);
} else if (firstChar.equals("1")) {
if ("".equals(stringN.substring(1, tempLen))) {
ans += 1;
} else if (!"".equals(stringN.substring(1, tempLen))) {
ans += Integer.parseInt(stringN.substring(1, tempLen)) + 1;
}
}
if (tempLen > 1) {
ans += Integer.parseInt(firstChar) * (tempLen - 1) * Math.pow(10, tempLen - 2);
}
stringN = stringN.substring(1);
}
return ans;
}
}
被除数与除数
package com.sly.uploadfile.algorithm; /** * Created by fmgao on 2019/7/9. * * 给定两个整数,被除数 dividend和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。 * 返回被除数 dividend除以除数 divisor得到的商。 */ public class Divide01 { public static int divide(int dividend, int divisor) { if (divisor == 0 || (dividend == Integer.MIN_VALUE && divisor == -1)) { return Integer.MAX_VALUE; } int sign = ((dividend < 0) ^ (divisor < 0)) ? -1 : 1;// 异或运算 long ms = (long) dividend; long ns = (long) divisor; ms = Math.abs(ms); ns = Math.abs(ns); int num = 0; while (ms >= ns) { long m = ns; long n = 1; while (ms >= (m << 1)) { m <<= 1; n <<= 1; } num += n; ms -= m; } return num * sign; } public static void main(String[] args) { int a = divide(46, 3); System.out.println(a); } }
数字异或
package com.sly.uploadfile.algorithm; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.List; /** * Created by fmgao on 2019/6/24. * <p> * 给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。 * <p> * 字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。 * <p> * Example 1: * <p> * Input: * s: "cbaebabacd" p: "abc" * <p> * Output: * [0, 6] * <p> * Explanation: * The substring with start index = 0 is "cba", which is an anagram of "abc". * The substring with start index = 6 is "bac", which is an anagram of "abc". * <p> * Example 2: * <p> * Input: * s: "abab" p: "ab" * <p> * Output: * [0, 1, 2] * <p> * Explanation: * The substring with start index = 0 is "ab", which is an anagram of "ab". * The substring with start index = 1 is "ba", which is an anagram of "ab". * The substring with start index = 2 is "ab", which is an anagram of "ab". */ @Slf4j public class EctopicElementService { public static List<Integer> findAnagrams(String s, String p) { List<Integer> list = new ArrayList<>(); int lens = s.length(); int lenp = p.length(); if (lens < lenp) { return list; } for (int i = 0; i <= lens - lenp; i++) { int[] t = new int[26]; for (int j = 0; j < lenp; j++) { t[s.charAt(i + j) - 'a']++; t[p.charAt(j) - 'a']--; } boolean flag = true; for (int j = 0; j < t.length; j++) { if (t[j] != 0) { flag = false; break; } } if (flag) { list.add(i); } } // log.info("list====" + list); return list; } public static void main(String[] args) { List<Integer> anagrams = findAnagrams("cbaebabacd", "abc"); System.out.println(anagrams); } }
括号成对校验
package com.sly.uploadfile.algorithm; import java.util.Stack; /** * Created by fmgao on 2019/6/28. */ public class EffectiveParentheses { public static boolean isValid(String s) { if (s == "" || s.length() == 0) { return true; } Stack stack = new Stack(); stack.push(s.charAt(0)); for (int i = 1; i < s.length(); i++) { if (!stack.isEmpty()) { if (stack.peek().equals((char) (s.charAt(i) - 1)) || stack.peek().equals((char) (s.charAt(i) - 2))) { stack.pop(); } else { stack.push(s.charAt(i)); } } else { stack.push(s.charAt(i)); } } if (stack.isEmpty()) { return true; } return false; } public static boolean isValid2(String s) { Stack<Character> stack = new Stack<>(); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (ch == '(' || ch == '[' || ch == '{') { stack.push(ch); } else { if (stack.isEmpty()) { return false; } char topChar = stack.pop(); if (ch == ')' && topChar != '(') { return false; } else if (ch == ']' && topChar != '[') { return false; } else if (ch == '}' && topChar != '{') { return false; } } } return stack.isEmpty(); } public static void main(String[] args) { long startTime = System.nanoTime(); boolean res = isValid("()(){}{}(){}()[][]{}"); long endTime = System.nanoTime(); System.out.println(res); System.out.println("程序运行时间: " + (endTime - startTime) + "ms"); long startTime2 = System.nanoTime(); boolean res2 = isValid2("()(){}{}(){}()[][]{}"); long endTime2 = System.nanoTime(); System.out.println(res2); System.out.println("程序运行时间: " + (endTime2 - startTime2) + "ms"); } }
找俩个子串拼接位置
package com.sly.uploadfile.algorithm; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** * Created by fmgao on 2019/7/3. */ public class FindSonChars { public static void main(String[] args) { String s = "barfoothefoobarman"; String[] words = {"foo", "bar"}; FindSonChars findSonChars = new FindSonChars(); List<Integer> list = findSonChars.findSubstring(s, words); for (Integer a : list) { System.out.println(a); } } /** * 1、 字符串和数组都是空 就return 空数组 * 2、 * * @param s * @param words * @return */ public List<Integer> findSubstring(String s, String[] words) { List<Integer> result = new ArrayList<Integer>(); // 如果s,或者是words为空,那么也返回一个空的列表 if (s.length() == 0 || s == null || words.length == 0 || words == null) { return result; } int size = words[0].length(), length = words.length; // 把字符串数组中的的字符串全部插入HashMap中 HashMap<String, Integer> map = generate(words); // 窗口的不同的起点,有size个不同的起点 for (int i = 0; i < size; i++) { HashMap<String, Integer> window = new HashMap<>(); // 一个滑动的窗口 int left, right; left = right = i; while (right <= s.length() - size && left <= s.length() - length * size) { String word = s.substring(right, right + size); incr(window, word); if (!map.containsKey(word)) { window.clear(); right += size; left = right; continue; } while (window.get(word) > map.get(word)) { String w = s.substring(left, left + size); decr(window, w); left += size; } right += size; if (right - left == size * length) { result.add(left); } } } return result; } private HashMap<String, Integer> generate(String[] strs) { HashMap<String, Integer> map = new HashMap<>(); for (String str : strs) { incr(map, str); } return map; } private void incr(HashMap<String, Integer> map, String str) { map.put(str, map.getOrDefault(str, 0) + 1); } private void decr(HashMap<String, Integer> map, String str) { Integer num = map.get(str); if (num <= 1) { map.remove(str); } else { map.put(str, num - 1); } } }
二分查找升级版
package com.sly.uploadfile.algorithm; /** * Created by fmgao on 2019/11/19. * <p> * 力扣算法】34-在排序数组中查找元素的第一个和最后一个位置 * 给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。 * <p> * 你的算法时间复杂度必须是 O(log n) 级别。 * <p> * 如果数组中不存在目标值,返回 [-1, -1]。 * <p> * 示例 1: * 输入: nums = [5,7,7,8,8,10], target = 8 * 输出: [3,4] * 示例 2: * 输入: nums = [5,7,7,8,8,10], target = 6 * 输出: [-1,-1] */ public class FirstLastSortArray { public static void main(String[] args) { int[] nums = {5, 7, 8, 8, 8, 10}; int target = 8; int[] ints = searchSort2(nums, target); for (int i : ints) { System.out.println(i); } } /** * 二分查找的升级版。以searchBegin为例, * <p> * 当nums[mid]>target时,向左查找, * 当nums[mid]=targe时,向左查找。 * 这样所有情况下,范围都会缩小,直到 l == r 为止,这时如果 该位置里的数 == target,则返回该位置,否则返回-1。 * <p> * searchEnd同理 * * @param nums * @param target * @return */ public static int[] searchSort2(int[] nums, int target) { if (nums == null || nums.length == 0) { return new int[]{-1, -1}; } int l = 0, r = nums.length; int mid = (l + r) / 2; int p = -1; while (l < r) { // 中间 if (nums[mid] == target) { p = mid; break; } // target 在左边 if (nums[mid] > target) { if (r == mid) break; r = mid; mid = (l + r) / 2; } else { // 在右边 if (l == mid) break; l = mid; mid = (l + r) / 2; } } if (p == -1) { return new int[]{-1, -1}; } else { int a = p, b = p; while (a > 0 && nums[a - 1] == target) a--; while (b < nums.length - 1 && nums[b + 1] == target) b++; return new int[]{a, b}; } } }