算法题
2016-12-04
纪念解决第一个算法题:TWO SUM
第一种解法:
public class twosum2 { public static void main(String[] args) { // TODO 自动生成的方法存根 twosum2 twosum = new twosum2(); //实例化这个类,第一个是类名,空格后面是实例化的类名 int[] nums = new int[4]; //输入数组 int target = 6; nums[0] = 1; nums[1] = 3; nums[2] = 4; nums[3] = 5; twosum.Twosum(nums, target); //调用方法,第一个是实例化的类名,。后面是调用函数名 int[] result = twosum.Twosum(nums, target); //使用调用方法的返回值 for(int i = 0; i < twosum.Twosum(nums, target).length; ++i){ System.out.println(result[i]); } } //以上是测试部分,以下是算法部分 public int[] Twosum(int[] nums, int target) { int[] result = new int [2]; for (int i = 0; i < nums.length; i++) { for (int j = i + 1; j < nums.length; j++) { if (nums[i] + nums[j] == target) { result[0] = i + 1; result[1] = j + 1; break; } } } return result; } }
第二种解法:
public class Solution { /* * @param numbers : An array of Integer * @param target : target = numbers[index1] + numbers[index2] * @return : [index1 + 1, index2 + 1] (index1 < index2) */ public static int[] twoSum(int[] numbers, int target) { HashMap<Integer, Integer> map = new HashMap<>(); //target = numbers[i] + numbers[j] //target - numbers[i] = numbers[j] ==>找target变为找numbers[j] //利用HashMap记录数值的位置,先用map.put写入数据,并且任然记录i的位置 //判断后出现的值(if语句内的)是否曾出现过,就是在已有的map内,如果存在就表示目前这个值和之前的某个值之和为target, //而且之前的值得位置记录在map中,就是map.get(numbers[i]) for (int i = 0; i < numbers.length; i++) { if (map.get(numbers[i]) != null) { int[] result = {map.get(numbers[i]), i}; return result; } map.put(target - numbers[i], i); } int[] result = {}; return result; }
}
2016-12-05
字符串查找
自己的第一种解法:
主要需要注意的是要考虑 source字符串和target字符串分别是null的情况,当任意一个字符串是null时,都无法调用方法,所以在调用方法的时候一定要分情况考虑。
public int strStr(String source, String target) { if (source == null || target == null) { return -1; } else { int x = source.indexOf(target); return x; } }
优解
注意最里面是对target字符串循环检测,还有注意用不等于!=来做循环条件。
class Solution { /** * Returns a index to the first occurrence of target in source, * or -1 if target is not part of source. * @param source string to be scanned. * @param target string containing the sequence of characters to match. */ public int strStr(String source, String target) { if (source == null || target == null) { return -1; } else { int n = target.length(); int m = source.length(); int j = 0; for (int i = 0; i < m - n + 1; i++) { for (j = 0; j < n; j++) { if (source.charAt(i + j) != target.charAt(j)) { break; } } if (j == n) { return i; } } return -1; } } }
2016-12-07
Last position of target
return result 语句运行之后直接结束子方法的解析返回主方法,等同于一个break。
注意理解二分法,无限逼近的思想,还有注意null和目标处于数组的收尾位置的特殊情况,数组中不存在目标数也要有输出(-1)。
但是我有个疑问,为什么在测试算法的时候,一定要在最后加上一个 return (xx): 因为 int 型方法,需要你返回一个整形,即便是你考虑了所有情况,但是还是要满足java 的语法要求。
说白了就是你考虑到最后一种情况时,就不用写出来了,直接把结果return 回去不就好了?
public class Solution { /** * @param nums: An integer array sorted in ascending order * @param target: An integer * @return an integer */ public int lastPosition(int[] nums, int target) { if (nums == null || nums.length == 0) { return -1; } int start = 0; int end = nums.length - 1; while (start + 1 < end) { int mid = start + (end - start) / 2; if (nums[mid] == target) { start = mid; } else if (nums[mid] < target) { start = mid; // or start = mid + 1 } else { end = mid; // or start = mid - 1 } } if (nums[end] == target) { return end; } if (nums[start] == target) { return start; } return -1; } }
Search and insert
同样是二分法,需要注意的是要考虑目标数大于等于数组的最后一个数;还有小于等于第一个数的情况,这些特殊情况要单独用if语句表示出来。
public class Solution { /** * param A : an integer sorted array * param target : an integer to be inserted * return : an integer */ public int searchInsert(int[] A, int target) { if (A == null || A.length == 0) { return 0; } int start = 0; int end = A.length - 1; while (start + 1 < end) { int mid = start + (end - start) / 2; if (A[mid] == target) { return mid; //System.out.println(mid);//start = mid; } else if (A[mid] < target) { start = mid; // or start = mid + 1 } else { end = mid; // or start = mid - 1 } } if (A[end] < target) { return end + 1; } else if (A[end] == target) { return end; } if (A[start] < target && A[end] > target) { return start + 1; } if (A[start] > target || A[start] == target) { return 0; } return 0; } }
2016-12-08 00:34:39
binarySearch
纪念第一次lintcode算法一次性AC。
这一问题注意是寻找第一个target出现的位置,而且是升序数组,所以直接考虑用小于做判断,而且target一定是在二分法寻找的最终两个相邻的整数之中的一个,判断并返回其位置,或者不存在那么返回-1。
class Solution { /** * @param nums: The integer array. * @param target: Target to find. * @return: The first position of target. Position starts from 0. */ public int binarySearch(int[] nums, int target) { if (nums == null || nums.length == 0) { return -1; } int start = 0; int end = nums.length - 1; int mid; while (start < end - 1) { mid = start + (end - start) / 2; if (nums[mid] < target) { start = mid; } else { end = mid; } } if (nums[end] == target) { return end; } if (nums[start] == target) { return start; } return -1; } }
2016-12-08 18:28:09
find peak
lintcode和leetcode对于这个题目的要求不一样,所以分别给出下面第一种和第二种算法。
lintcode给出的约束条件更多,考虑的范围小一点,算法就相对简单一点。
class Solution { /** * @param A: An integers array. * @return: return any of peek positions. */ public int findPeak(int[] A) { int start; int end = A.length - 1; for (start = 1; start < end; start++) { if (A[start] > A[start + 1]) { return start; } } return 1; } }
public class Solution { public int findPeakElement(int[] nums) { int start; int end = nums.length - 1; if (nums.length == 1) { return 0; } else { for (start = 0; start < end; start++) { if (nums[start] > nums[start + 1]) { return start; } } } return end; } }
2016-12-08 22:52:44
first Bad Version
二分法,循环到二分法最后一步,两个数之间判断然后取一个出来返回,很像binarySearch。
class Solution { /** * @param n: An integers. * @return: An integer which is the first bad version. */ public int findFirstBadVersion(int n) { int start = 1; int end = n; while (start < end - 1) { int mid = start + (end - start) / 2; if (SVNRepo.isBadVersion(mid)) { end = mid; } else { start = mid; } } if (SVNRepo.isBadVersion(start)) { return start; } return end; } }
2016-12-09 00:31:59
search Matrix
这个要好好理解一下时间复杂度,我自己的解法超出限制时间,时间复杂度不好。
public class Solution { public boolean searchMatrix(int[][] matrix, int target) { if (matrix == null || matrix.length == 0) { return false; } if (matrix[0] == null || matrix[0].length == 0) { return false; } int row = matrix.length; int column = matrix[0].length; int start = 0; int end = row * column - 1; while (start + 1 < end) { int mid = start + (end - start) / 2; int number = matrix[mid / column][mid % column]; if (number == target) { return true; } else if (number < target) { start = mid; } else { end = mid; } } if (matrix[start / column][start % column] == target) { return true; } else if (matrix[end / column][end % column] == target) { return true; } return false; } }
2017-01-13 16:56:08
Subsets
第一次接触ArrayList(动态数组)
public class Solution { public ArrayList<ArrayList<Integer>> subsets(int[] num) { ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>(); if(num == null || num.length == 0) { return result; } ArrayList<Integer> list = new ArrayList<Integer>(); Arrays.sort(num); subsetsHelper(result, list, num, 0); return result; } private void subsetsHelper(ArrayList<ArrayList<Integer>> result, ArrayList<Integer> list, int[] num, int pos) { result.add(new ArrayList<Integer>(list)); for (int i = pos; i < num.length; i++) { list.add(num[i]); subsetsHelper(result, list, num, i + 1); list.remove(list.size() - 1); } } }