LeetCode: 给定数组找目标和的下标索引数组(1,167,560,653, 713,209, 152)

---恢复内容开始---

1   Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,  Because nums[0] + nums[1] = 2 + 7 = 9,   return [0, 1].
//函数参数 为目标数组的应用,和目标和,返回索引数组
vector<int> twoSum(vector<int> &numbers, int target)
{
    //数组元素是键,值是对应的指标
    unordered_map<int, int> hash;
    vector<int> result;
    for (int i = 0; i < numbers.size(); i++) {
        //看目标数减去numbers[i] 余数是多少
        int numberToFind = target - numbers[i];
        //看有没有这个余数的键值
        if (hash.find(numberToFind) != hash.end()) {
            //如果有 返回索引数组
            result.push_back(hash[numberToFind]);
            result.push_back(i);            
            return result;
        }
        //不然,更新hasn数组,根据解唯一 这个更新及时有重复 也不会破坏
        hash[numbers[i]] = i;
    }
    return result;
}

167  Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.

Note:

  • Your returned answers (both index1 and index2) are not zero-based.
  • You may assume that each input would have exactly one solution and you may not use the same element twice.

Example:

Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.
//也可以使用以上的方法  这个索引是从1开始的
vector<int> twoSum(vector<int>& numbers, int target) { int l = 0; int r = numbers.size() -1; while(l < r){ if(numbers[l] + numbers[r] == target){ //注意这个初始化方式 vector<int> res{l+1,r+1}; return res; } else if(numbers[l] + numbers[r] > target){ r--; } else{ l++; } } }

560  Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k.

Example 1:

      Input:nums = [1,1,1], k = 2    Output: 2

Note:  The length of the array is in range [1, 20,000].  The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7].

 

// hashmap + preSum
/*
    1. Hashmap<sum[0,i - 1], frequency>
    2. sum[i, j] = sum[0, j] - sum[0, i - 1]    --> sum[0, i - 1] = sum[0, j] - sum[i, j]
        k           sum      hashmap-key     -->  hashmap-key  =  sum - k
    3. now, we have k and sum.  
        As long as we can find a sum[0, i - 1], we then get a valid subsequence
        which is as long as we have the hashmap-key,  we then get a valid subsequence
    4. Why don't map.put(sum[0, i - 1], 1) every time ?
        if all numbers are positive, this is fine
        if there exists negative number, there could be preSum frequency > 1
*/    

/*
    for i, cum is the sum of nums[0] + nums[1] + ... + nums[i]. Assuming there is an item called 
    nums[j] in nums[0] + nums[1] + ... nums[j] + ... + nums[i], if nums[0] + nums[1] + ... + nums[j]
    equals to cum - k, then, the sum of subarray nums[j + 1] + nums[j + 2] + ... + nums[i] equals
    to cum - (cum - k) = k, it is one of the subarray which we are looking for. rec[cum - k] is
    the number of the subarray which begins at index 0 with sum cum - k.
*/
class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        int cum=0;        // cumulated sum
        map<int,int> rec; // prefix sum recorder
        int cnt = 0;      // number of found subarray
        rec[0]++;         // to take into account those subarrays that begin with index 0
        for(int i=0;i<nums.size();i++){
            cum += nums[i];
            //sum[i, j] = sum[0, j] - sum[0, i - 1]
            //由于现在的结果是cum  为了凑出k我们还需要 cum - k 的个数
            cnt += rec[cum-k];
            rec[cum]++;
        }
        return cnt;
    }
};

 

653. Two Sum IV - Input is a BST

Given a Binary Search Tree and a target number, return true if there exist two elements in the BST(二叉搜索树) such that their sum is equal to the given target.

Example 1:
Input:
                5
               / \
              3 6
              / \ \
             2 4 7

       Target = 9

     Output: True
Example 2:
Input:
5
/ \
3 6
/ \ \
2 4 7

Target = 28

Output: False

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool findTarget(TreeNode* root, int k) {
        unordered_set<int> set;
        return dfs(root, set, k);
    }
    
    bool dfs(TreeNode* root, unordered_set<int>& set, int k){
        if(root == NULL)return false;
        if(set.count(k - root->val))return true;
        set.insert(root->val);
        return dfs(root->left, set, k) || dfs(root->right, set, k);
    }
};

更多解法参考:https://leetcode.com/problems/two-sum-iv-input-is-a-bst/discuss/106059/JavaC++-Three-simple-methods-choose-one-you-like

713. Subarray Product Less Than K

Your are given an array of positive integers nums.

Count and print the number of (contiguous) subarrays where the product of all the elements in the subarray is less than k.

Example 1:
Input: nums = [10, 5, 2, 6], k = 100
Output: 8
Explanation: The 8 subarrays that have product less than 100 are: [10], [5], [2], [6], [10, 5], [5, 2], [2, 6], [5, 2, 6].
Note that [10, 5, 2] is not included as the product of 100 is not strictly less than k.
Note:

0 < nums.length <= 50000.
0 < nums[i] < 1000.
0 <= k < 10^6.

The idea is always keep an max-product-window less than K; 

Every time shift window by adding a new number on the right(j),  if the product is greater than k, then try to reduce numbers on  the left(i), until the subarray product fit less than k again, (subarray could be empty);

Each step introduces x new subarrays, where x is the size of the current window (j + 1 - i);

example:
for window (5, 2), when 6 is introduced, it add 3 new subarray: (5, (2, (6)))
* for window (5, 2, 6), when 6 is introduced, it add 3 new subarray:
* (6)
* (2, 6)
* (5, 2, 6)
*/

class Solution {
public:
    int numSubarrayProductLessThanK(vector<int>& nums, int k) {
        if (k == 0) return 0;
        int cnt = 0;
        int pro = 1;
        for (int i = 0, j = 0; j < nums.size(); j++) {
            pro *= nums[j];
            //固定最右 确保 每次子数组 都不一样
            while (i <= j && pro >= k) {
                pro /= nums[i++];
            }
            //这里的i有 记录 个数 的作用 
            //如果i=0  说明 从 【j-1,j】,...,【0,j】 这 j+1 
            //连续子数组都可以
            cnt += j - i + 1;
        }
        return cnt;
    }
};

 

209. Minimum Size Subarray Sum

Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead.

Example:

Input: s = 7, nums = [2,3,1,2,4,3]
Output: 2
Explanation: the subarray [4,3] has the minimal length under the problem constraint.
Follow up:
If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).

public int minSubArrayLen(int s, int[] a) {
  if (a == null || a.length == 0)
    return 0;
  
  int i = 0, j = 0, sum = 0, min = Integer.MAX_VALUE;
  
  while (j < a.length) {
    //每次迭代最右 确保 每次遍历 数据不同
    sum += a[j++];
    
    //满足题目要求 大于 s
    while (sum >= s) {
      //从最左开始遍历 确定 最小  
      min = Math.min(min, j - i);
      sum -= a[i++];
    }
  }
  
  return min == Integer.MAX_VALUE ? 0 : min;
}

152. Maximum Product Subarray

Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product.

Example 1:

Input: [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.
Example 2:

Input: [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.

int maxProduct(int A[], int n) {
    // store the result that is the max we have found so far
    int r = A[0];

    // imax/imin stores the max/min product of
    // subarray that ends with the current number A[i]
    for (int i = 1, imax = r, imin = r; i < n; i++) {
        // multiplied by a negative makes big number smaller, small number bigger
        // so we redefine the extremums by swapping them
        if (A[i] < 0)
            swap(imax, imin);

        // max/min product for the current number is either the current number itself
        // or the max/min by the previous number times the current one
        imax = max(A[i], imax * A[i]);
        imin = min(A[i], imin * A[i]);

        // the newly computed max value is a candidate for our global result
        r = max(r, imax);
    }
    return r;
}

一个加法的题,解决方法类似;

/*
一个数组有 N 个元素,求连续子数组的最大和。 例如:[-1,2,1],
和最大的连续子数组为[2,1],其和为 3
输入描述:
输入为两行。 第一行一个整数n(1 <= n <= 100000),表示一共有n个元素 第二行为n个数,
即每个元素,每个整数都在32位int范围内。以空格分隔。
输出描述:
所有连续子数组中和最大的值。

输入例子1:
3 -1 2 1

输出例子1:
3
*/

#include <iostream>
#include <vector>
using namespace std;
int main(void)
{
    int n, max;
    cin >> n;
    vector<int> list(n, 0), dp(list);
    for (int i = 0; i < n; i++)           //创建数组
        cin >> list[i];
    max = dp[0] = list[0];
    for (int i = 1; i < n; i++)           //由于是连续的,因此只需要更新对
    {                                     //角线即可,之前部分遇上一行相同
        if (list[i] + dp[i - 1] > list[i])//如果上一对角线上的数和更大 主要看dp[i-1]是否为负
            dp[i] = list[i] + dp[i - 1];  //填入对应位置
        else
            dp[i] = list[i];              //否则,即为这个数本身
        if (max < dp[i]) max = dp[i];     //寻找数组中最大的
            
    }
    cout << max << endl;
    return 0;
}

 

posted @ 2018-10-09 17:39  十八子~  阅读(240)  评论(0编辑  收藏  举报