LintCode--【问题记录】
给出一个数组,将这个数组排序,使得所有的奇数在偶数前面,注意奇数之间、偶数之间的相对顺序不变
方法1:新建一个list 存放偶数,将数组中的奇数直接放在前面,然后把list中的偶数添加到数组后面
时间复杂度O(n) 空间复杂度O(n)
public void reorder(int[] arr) { int len = arr.length; List<Integer> list = new ArrayList<Integer>(); int curri = 0; for (int i = 0; i < len; i++) { if (arr[i] % 2 == 0) { list.add(arr[i]); } else { arr[curri] = arr[i]; curri++; } } int j = 0; for (int i = curri; i < len; i++) { arr[i] = list.get(j); j++; } }
方法2:类似于冒泡排序,相邻两个数,如果前面为偶数后面为奇数,就交换
时间复杂度O(n*n) 空间复杂度O(1)
public static void reOrder3(int[] arr){ int len = arr.length; for(int i = 0 ; i < len ; i++){ for(int j = len-1 ; j >i ; j--){ //注意,这里下标需要从后向前,可以保证每一趟遍历会把奇数移到前面, //如果从前向后,则不行,例如 2,4,6,8,1,3,5 if(arr[j-1]%2 ==0 && arr[j]%2==1){ //前偶后奇 int temp = arr[j-1]; arr[j-1] = arr[j]; arr[j] = temp; } } } }
方法2.2 遇到一个偶数,就向后找到第一个奇数,然后将前面的偶数向后移动一位,将奇数移到前面。
时间复杂度O(n*n) 空间复杂度O(1)
//使用常量的空间 public static void reOrder2(int[] arr) { int len = arr.length; int i_odd = 1; //指向奇数 for (int index = 0; index < len; index++) { if (arr[index] % 2 == 0) { // 找到一个偶数 i_odd = Math.max(i_odd, index+1); while(i_odd<len){ //注意,i_odd只会向后 //找到了奇数 if (arr[i_odd] % 2 == 1) break; i_odd++; } if(i_odd==len) return; //已经没有未处理的奇数了 // 将i到i_odd-1的数字都向后移动一位 int temp = arr[i_odd]; for (int cur = i_odd - 1; cur >= index; cur--) { arr[cur + 1] = arr[cur]; } arr[index] = temp; } } }
43 maximum subarray iii
问题:
给定一个整数数组和一个整数k,找出k个不重叠子数组使得它们的和最大。
每个子数组的数字在数组中的位置应该是连续的。
返回最大的和
样例
给出数组[-1,4,-2,3,-2,3]以及k=2,返回 8
要求:时间复杂度 O(n)
思路:类似于leetcode中买卖股票的问题,进行K次交易。
注意:两个问题是有区别的,股票价格总是正的,而且股票求的是收益,而不是股价的和
代码:
public static int maxSubArray(ArrayList<Integer> nums, int k) { if (nums == null) return 0; int len = nums.size(); if (len < k) return 0; //globalMax[i][j] ,代表从nums[0...j]中找出i个不重叠的子数组的最大和(元素最远到j) int[][] globalMax = new int[k + 1][len + 1]; for (int i = 1; i <= k; i++) { int localMax = Integer.MIN_VALUE; // 数组长度小于i不能进行划分 for (int j = i - 1; j < len; j++) { localMax = Math.max(localMax, globalMax[i - 1][j]) + nums.get(j); if (j == i - 1) //每一行的第一个要单独处理 globalMax[i][j + 1] = localMax; else globalMax[i][j + 1] = Math.max(globalMax[i][j], localMax); } }return globalMax[k][len]; }
77 最长公共子序列
给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度。
样例
给出"ABCD" 和 "EDCA",这个LCS是 "A" (或 D或C),返回1
给出 "ABCD" 和 "EACB",这个LCS是"AC"返回 2
给出"ABCD" 和 "EDCA",这个LCS是 "A" (或 D或C),返回1
给出 "ABCD" 和 "EACB",这个LCS是"AC"返回 2
注:最长公共子序列不要求一定连续,只要顺序一致即可
方法1:穷举 O(2^m , 2^n)
方法2:递归 O(m*n)+O(m+n)
public int longestCommonSubsequence(String A, String B) { int lenA = A.length(); int lenB = B.length(); //c[i][j]存放的为A[0..i-1] B[0..j-1]的字符串的最大子序列 /* * 若 i==0 || j ==0 则 c[i][j]=0 * 若 i,j>0 && A[i]==B[j] 则 c[i][j]=c[i-1][j-1]+1 * 若 i,j>0 && A[i]!=B[j] 则 c[i][j]=max(c[i-1][j],c[i][j-1]) */ int[][] c = new int[lenA+1][lenB+1]; for(int i = 1 ; i <= lenA ; i ++ ){ for(int j = 1 ; j <= lenB ; j ++ ){ if(A.charAt(i-1) == B.charAt(j-1)){ c[i][j] = c[i-1][j-1]+1; }else if(c[i-1][j] >= c[i][j-1]){ c[i][j] = c[i-1][j]; }else{ c[i][j] = c[i][j-1]; } } }return c[lenA][lenB]; }
结果:


浙公网安备 33010602011771号