二分查找
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};
}
}
}