一些思路不是很清晰的算法题
正则表达式匹配
public boolean isMatch(String s, String p) {
if (s == null || p == null)
return false;
int m = s.length(), n = p.length();
boolean[][] dp = new boolean[m + 1][n + 1];
dp[0][0] = true;
for (int j = 1; j <= n; j++) {
if (p.charAt(j - 1) == '*') {
dp[0][j] = dp[0][j - 2];
}
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s.charAt(i-1) == p.charAt(j-1) || p.charAt(j-1) == '.') {
dp[i][j] = dp[i-1][j-1];
} else if (p.charAt(j-1) == '*') {
if (s.charAt(i-1) == p.charAt(j-2) || p.charAt(j-2) == '.') {
dp[i][j] = dp[i][j-2] || dp[i-1][j-2] || dp[i-1][j]; // 抵消0、1、多
} else {
dp[i][j] = dp[i][j-2];
}
}
}
}
return dp[m][n];
}
字符串转数字
BST与双向链表
平衡二叉树
public boolean isBalanced(TreeNode root) {
return depth(root) != -1;
}
public int depth(TreeNode root) {
if (root == null)
return 0;
int leftDepth = depth(root.left);
if (leftDepth == -1)
return -1;
int rightDepth = depth(root.right);
if (rightDepth == -1)
return -1;
if (Math.abs(leftDepth - rightDepth) > 1)
return -1;
return 1 + Math.max(leftDepth, rightDepth);
}
单向链表排序
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
/** 单向链表快速排序 */
public void quickSort(ListNode head) {
if (head==null || head.next==null)
return;
quickSort(head, null);
}
private void quickSort(ListNode head, ListNode tail) {
if (head == tail || head.next == tail)
return;
ListNode pivot = partition(head, tail);
quickSort(head, pivot);
quickSort(pivot.next, tail);
}
private ListNode partition(ListNode head, ListNode tail) {
int pivot = head.val;
ListNode left = head, right = head.next;
while (right != tail) {
if (right.val >= pivot) {
right = right.next;
} else {
left.val = right.val;
left = left.next;
right.val = left.val;
right = right.next;
}
}
left.val = pivot;
return left;
}
数组中的逆序对
思路:借助归并排序的过程,进行统计。类似于判断平衡树,借助求深度的过程进行判断。
数组原地置换
给定一个数组a1,a2,a3,...an,b1,b2,b3..bn,最终把它置换成a1,b1,a2,b2,...an,bn。类似于完美洗牌问题。我觉得写出时间O(nlogn)、空间O(1)的就足够了。
public int[] shuffle(int[] arr, int n) {
int[] nums = Arrays.copyOf(arr, arr.length);
shuffle(nums, n, 0, nums.length - 1);
return nums;
}
private void shuffle(int[] nums, int len, int start, int end) {
if (len == 1) return;
// 处理len为奇数的情况,将前半部分的最后一个数换到倒第二的位置
if ((len & 1) != 0) {
int temp = nums[start + len - 1];
for (int i = start + len; i < end; i++) {
nums[i - 1] = nums[i];
}
nums[end - 1] = temp;
len--;
end -= 2;
}
// 将需要shuffle的部分数组等分为4部分,将第2、3部分整体置换
int mid = start + ((end - start) >>> 1);
int left = start + ((mid - start) >>> 1) + 1, right = mid + 1, temp;
while (left <= mid) {
temp = nums[left];
nums[left++] = nums[right];
nums[right++] = temp;
}
// 递归分治进行置换
shuffle(nums, len >>> 1, start, mid);
shuffle(nums, len >>> 1, mid + 1, end);
}
猿辅导面试的两道算法题(LeetCode 93.复原IP地址、求有序数组里值<=target的最大序号)
这两道题乍看不是很难,但是细节比较重要。第一道题注意“127001”这种情况,第二道题注意可能造成死循环。```
public List<String> restoreIpAddresses(String s) {
List<String> res = new ArrayList<>();
helper(s, res, new int[4], 0);
return res;
}
private void helper(String s, List<String> res, int[] temp, int idx) {
if (idx == 4) {
if (s.length() == 0) {
StringBuilder sb = new StringBuilder();
sb.append(temp[0]);
for (int i = 1; i < 4; i++) {
sb.append('.').append(temp[i]);
}
res.add(new String(sb));
}
} else {
int num;
for (int len = 1; len <= 3 && len <= s.length(); len++) {
num = Integer.parseInt(s.substring(0, len));
// 0、1、00、01、11、000、001、010、100、345 里面
// 只有 0、1、11、100 合法,即 数值为0且长度为0、数值在1-255之间且第一位不为0 两种
if ((num == 0 && len == 1) || (num > 0 && num < 256 && s.charAt(0) != '0')) {
temp[idx] = num;
helper(s.substring(len), res, temp, idx + 1);
}
}
}
}
public static int rightBound(int[] nums, int target) {
int lo = 0, hi = nums.length, mid;
while (lo < hi) {
mid = lo + ((hi - lo) >>> 1);
if (nums[mid] <= target)
lo = mid + 1;
else
hi = mid;
}
return lo - 1;
}

浙公网安备 33010602011771号