LeetCode基础题——数组篇

目前只是收录了基础题中的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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值