目前只是收录了基础题中的10个
1.去除有序数组中的重复元素
/**
* 去除数组中重复元素,返回新数组大小
*/
public static int removeDuplicates(int[] nums) {
if (nums.length <= 1)
return nums.length;
int size = 1;
for (int i = 1; i < nums.length; i++) {
int flag = nums[size - 1];
if (flag != nums[i]) {
nums[size] = nums[i];
size++;
}
}
return size;
}
2. 卖股票的最大利润
/**
* 卖股票最大利润,输入一个数组,只要后一个元素比前面一个大,即可完成一次买入卖出操作
* 与上一题相似的地方在于,以i和i+1两个下标进行操作,这样就只需要用一个循环了
*/
public static int maxProfit(int[] prices) {
if (prices == null || prices.length < 2)
return 0;
int sum = 0;
for (int i = 0; i < prices.length - 1; i++) {
if (prices[i + 1] > prices[i])
sum = sum + (prices[i + 1] - prices[i]);
}
return sum;
}
3.旋转数组
/**
* (idx+k)%nums.length刚好是旋转后元素所在位置
*
* @param nums input
* @param k
* @return
*/
public static int[] rotate1(int[] nums, int k) {
k = k % nums.length;
int[] result = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
result[(k + i) % nums.length] = nums[i];
}
return result;
}
/**
* (idx+k)%nums.length刚好是旋转后元素所在位置
* 该方法是逐次交换一个
*
* @param nums input
* @param k
* @return
*/
public static void rotate2(int[] nums, int k) {
if (nums.length == 0 || k % nums.length == 0)
return;
int len = nums.length;
int start = 0;
int i = 0;
int cur = nums[i];
int cnt = 0;
while (cnt++ < len) {
i = (k + i) % len;
int temp = nums[i];
nums[i] = cur;
if (i == start) {
++start;
++i;
cur = nums[i];
} else {
cur = temp;
}
}
}
4. 判断是否存在重复元素
/**
* 算法遍历一次数组,遍历过程中,将每次遍历的数组元素按升序放到它相应的位置,那么这个元素必然>=它之前的元素。然后比较该元素与前一个元素是否相等。如果相等,则说明包含重复的元素。
*
* @param nums
* @return
*/
public boolean containsDuplicate(int[] nums) {
for (int i = 1; i < nums.length; i++) {
int j = i - 1;
int temp = nums[j + 1];
while (j >= 0 && nums[j] > temp) {
nums[j + 1] = nums[j];
j--;
}
nums[j + 1] = temp;
if (j >= 0 && nums[j] == nums[j + 1])
return true;
}
return false;
}
5. 找出只出现一次的元素
/**
* 仔细阅读题目,只有一个元素出现了一次,其他每个元素都出现了两次。可以转化为数学运算呀!异或操作,两个相同的数异或结果为0,一个数跟0异或是这个数本身。
*
* @param nums
* @return
*/
public static int singleNumber(int[] nums) {
int num = 0;
for (int i = 0; i < nums.length; i++) {
num ^= nums[i];
}
return num;
}
6. 两个数组的交集
/**
* 求两个数组的交集,使用一个map作为计数器,存储每个数字对应的出现次数
*
* @param nums1
* @param nums2
* @return
*/
public static int[] intersect1(int[] nums1, int[] nums2) {
Map<Integer, Integer> counter = new HashMap<Integer, Integer>();
for (int i = 0; i < nums1.length; i++) {
int key = nums1[i];
if (counter.keySet().contains(key)) {
counter.put(key, counter.get(key) + 1);
} else {
counter.put(key, 1);
}
}
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < nums2.length; i++) {
int key = nums2[i];
if (counter.keySet().contains(key) && counter.get(key) > 0) {
counter.put(key, counter.get(key) - 1);
list.add(key);
}
}
int[] result = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
result[i] = list.get(i);
}
return result;
}
7. 加一
/**
* 有两种情况:
* 最高位进位:那么比它低的位就全部是9,且加1后为0,需要新建一个长度为digits.length+1的新数组,0位置为1表示进位
* 最高位不进位:不需要进位则不需要新建数组,后续数字由更低位计算而来
*
* @param digits
* @return
*/
public static int[] plusOne(int[] digits) {
int carry = 1;
//不需要进位,从最低位开始计算
for (int i = digits.length - 1; i >= 0; i--) {
if (carry == 0) {
return digits;
}
int tmp = digits[i] + 1;
//0表示tmp没有大于10,只要不大于10就不需要进位,否则表示最低位进位
carry = tmp / 10;
digits[i] = tmp % 10;
}
//最高位需要进位
if (carry!=0){
//初始化数组,所有元素默认是0
int[] result =new int[digits.length+1];
result[0]=1;
return result;
}
return digits;
}
8. 将0元素移到末尾
/**
* 给定一个数组nums, 编写一个函数将所有 0 移动到它的末尾,同时保持非零元素的相对顺序。
*
* 例如, 定义 nums = [0, 1, 0, 3, 12],调用函数之后, nums 应为 [1, 3, 12, 0, 0]。
*
* 注意事项:
*
* 必须在原数组上操作,不要为一个新数组分配额外空间。
* 尽量减少操作总数。
*
* 思路很简单,使用使用两个索引lastIndex和curIndex,curIndex从后向前遍历直到其元素为0,然后根据lastIndex与curIndex之间的差值,将元素前移。
* @param nums
*/
public static void moveZeros(int[] nums){
int curIdx=nums.length-1;
int lastIdx =nums.length-1;
int count=0;
while (curIdx>=0){
if (nums[curIdx]==0){
count=lastIdx-curIdx;
for (int i = 0; i <count ; i++) {
nums [curIdx+i]=nums[curIdx+i+1];
}
nums[lastIdx]=0;
lastIdx--;
}
curIdx--;
}
}
9. 求和
/**
* 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个整数,并返回他们的数组下标。
* 暴力法:暴力法很简单。遍历每个元素 x,并查找是否存在一个值与 target - x 相等的目标元素。
* 该方法的时间复杂度为
* @param nums
* @param target
* @return
*/
public static int[] twoSum1(int[] nums,int target) throws IllegalAccessException {
for (int i = 0; i < nums.length ; i++) {
for (int j = i+1; j < nums.length ; j++) {
if (nums[j]==target-nums[i])
return new int[]{i,j};
}
}
throw new IllegalAccessException("No two sum solution");
}
/**
* 暴力法的时间复杂度成本太高,我们有必要进行优化,使用空间换取时间
* 使用map来存储数组元素及其下标:key-元素,value-下标
* @param nums
* @param target
* @return
*/
public static int[] twoSum2(int[] nums,int target){
Map<Integer,Integer> map=new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i],i);
}
for (int i = 0; i < nums.length; i++) {
int complement=target-nums[i];
if (map.containsKey(complement)&&map.get(complement)!=i){
return new int [] {
i,map.get(complement)
};
}
}
return null;
}
/**
* 事实上上述方法可以在一个for循环中完成
* @param nums
* @param target
* @return
*/
public static int[] twoSum3(int[] nums,int target){
Map<Integer,Integer> map=new HashMap<Integer, Integer> ();
for (int i = 0; i < nums.length; i++) {
int complement=target-nums[i];
if (map.containsKey(complement)&&map.get(complement)!=i){
return new int [] {
map.get(complement),i
};
}
map.put(nums[i],i);
}
return null;
}
10. 判断有效数独
/**
* 判断是否是有效数独
* 即输入一个9*9二维数组,1-9只能在同一行、同一列中出现一次,同时每个3*3矩阵中也只能出现一次
* @param board
* @return
*/
public static boolean isValidSudoku(char[][] board) {
Map<Integer, Integer>[] rows = new HashMap[9];
Map<Integer, Integer>[] columns = new HashMap[9];
Map<Integer, Integer>[] boxes = new HashMap[9];
for (int i = 0; i < 9; i++) {
rows[i] = new HashMap<Integer, Integer>();
columns[i] = new HashMap<Integer, Integer>();
boxes[i] = new HashMap<Integer, Integer>();
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
char num = board[i][j];
if (num != '.') {
int n = num;
int box_idx = (i / 3) * 3 + j * 3;
rows[i].put(n, rows[i].getOrDefault(n, 0) + 1);
columns[j].put(n, columns[j].getOrDefault(n, 0) + 1);
boxes[box_idx].put(n, boxes[box_idx].getOrDefault(n, 0) + 1);
//查看该值是否已经出现过
if (rows[i].get(n) > 1 || columns[j].get(n) > 1 || boxes[box_idx].get(n) > 1)
return false;
}
}
}
return true;
}
}