leetcode1

 5197. 最小绝对差

给你个整数数组 arr,其中每个元素都 不相同。

请你找到所有具有最小绝对差的元素对,并且按升序的顺序返回。

示例 1:

输入:arr = [4,2,1,3]
输出:[[1,2],[2,3],[3,4]]

示例 2:

输入:arr = [1,3,6,10,15]
输出:[[1,3]]

示例 3:

输入:arr = [3,8,-10,23,19,-4,-14,27]
输出:[[-14,-10],[19,23],[23,27]]

提示:

  • 2 <= arr.length <= 10^5
  • -10^6 <= arr[i] <= 10^6
/**
 * @param {number[]} arr
 * @return {number[][]}
 */
var minimumAbsDifference = function(arr) {
    let res = [];
    arr.sort((a, b)=>a-b);
    let c = Infinity;
    for(let i=0; i<arr.length-1; i++){
        let val = arr[i+1]-arr[i];
        if(val<c) {
           c = val
          res.length = 0;
        } 
        if(val === c){
           let temp = [];
            temp.push(arr[i], arr[i+1]);
            res.push(temp)
        }
    }
    return res
}
/*
var minimumAbsDifference = function(arr) {
    arr.sort((a, b)=>a-b);
    let map = new Map();
    let c = Infinity;
    for(let i=0; i<arr.length-1; i++){
        let val = arr[i+1]-arr[i];
        if(val<c) c = val 
        if(map.has(val)){
            let v = map.get(val);
            v.push([arr[i], arr[i+1]])
            map.set(val, v)
        }else{
            map.set(val, [[arr[i], arr[i+1]]])
        }
    }
    for(let [key, val] of map.entries()){
        if(key ===c){
            return val
        }
    }
};
*/

 未解决:

https://leetcode-cn.com/contest/weekly-contest-155

https://coding.imooc.com/lesson/315.html#mid=22379

5198. 丑数 III

请你帮忙设计一个程序,用来找出第 n 个丑数。

丑数是可以被 a 或 b 或 c 整除的正整数。

示例 1:

输入:n = 3, a = 2, b = 3, c = 5
输出:4
解释:The ugly numbers are 2, 3, 4, 5, 6, 8, 9, 10... The 3rd is 4.

示例 2:

输入:n = 4, a = 2, b = 3, c = 4
输出:6
解释:丑数序列为 2, 3, 4, 6, 8, 9, 12... 其中第 4 个是 6。

示例 3:

输入:n = 5, a = 2, b = 11, c = 13
输出:10
解释:丑数序列为 2, 4, 6, 8, 10, 11, 12, 13... 其中第 5 个是 10。

示例 4:

输入:n = 1000000000, a = 2, b = 217983653, c = 336916467
输出:1999999984

提示:

  • 1 <= n, a, b, c <= 10^9
  • 1 <= a * b * c <= 10^18
  • 本题结果在 [1, 2 * 10^9] 的范围内
/**
 * @param {number} n
 * @param {number} a
 * @param {number} b
 * @param {number} c
 * @return {number}
 */
// class Solution {
//     long gcd(long a, long b) {
//         if (b == 0) return a;
//         return gcd(b, a%b);
//     }
    

//     public int nthUglyNumber(int n, int a, int b, int c) {
//         long l = 0;
//         long r = Integer.MAX_VALUE;
//         while (l + 1 < r) {
//             long m = (l + r) / 2;
//             long cnt = m / a;
//             cnt += m / b;
//             cnt += m / c;
//             cnt -= m / ((long)a * b / gcd(a, b));
//             cnt -= m / ((long)a * c / gcd(a, c));
//             cnt -= m / ((long)b * c / gcd(b, c));
//             long tmp = (long)a * b / gcd(a, b);
//             cnt += m / (tmp*c / gcd(c, tmp));
//             if (cnt < n) {
//                 l = m;
//             } else {
//                 r = m;
//             }
//         }
//         return (int)r;
//     }

// }
// 最小公倍数
var gcd=function(a, b) {
        if (b == 0) return a;
        return gcd(b, a%b);
    }
var nthUglyNumber = function(n, a, b, c) {
    let l=0;
    let r = Infinity;
    while(l + 1 < r){
       let m = parseInt((l+r)/2);
       let cnt = parseInt(m / a);
       cnt += m / b;
       cnt += m / c; 
        cnt -= m / (a * b / gcd(a, b));
        cnt -= m / (a * c / gcd(a, c));
        cnt -= m / (b * c / gcd(b, c));
        let tmp = a * b / gcd(a, b);
        cnt += m / (tmp*c / gcd(c, tmp));
        if (cnt < n) {
            l = m;
        } else {
            r = m;
        }
    }
    return r
}
/*
var nthUglyNumber = function(n, a, b, c) {
    let s = Math.min(a, b, c)
    let res = [1];
      let i2=0,i3=0,i5=0,i=0;
      while(i++<n){
        let tmp=Math.min(a*res[i2],Math.min(b*res[i3],c*res[i5]));
        res.push(tmp);
        if(tmp==a*res[i2]) i2++;
        if(tmp==b*res[i3]) i3++;
        if(tmp==c*res[i5]) i5++;  
      }
    return res.pop()
// 超出时间限制
    // let s = Math.min(a, b, c), count=0;
    // while(true){
    //     if(s%a===0 || s%b===0 || s%c===0) count++;
    //     if(count === n) return s
    //     s++
    // }
};
*/

玩筹码

数轴上放置了一些筹码,每个筹码的位置存在数组 chips 当中。

你可以对 任何筹码 执行下面两种操作之一(不限操作次数,0 次也可以):

  • 将第 i 个筹码向左或者右移动 2 个单位,代价为 0。
  • 将第 i 个筹码向左或者右移动 1 个单位,代价为 1。

最开始的时候,同一位置上也可能放着两个或者更多的筹码。

返回将所有筹码移动到同一位置(任意位置)上所需要的最小代价。

示例 1:

输入:chips = [1,2,3]
输出:1
解释:第二个筹码移动到位置三的代价是 1,第一个筹码移动到位置三的代价是 0,总代价为 1。

示例 2:

输入:chips = [2,2,2,3,3]
输出:2
解释:第四和第五个筹码移动到位置二的代价都是 1,所以最小总代价为 2。

  • 1 <= chips.length <= 100
  • 1 <= chips[i] <= 10^9
/**
 * @param {number[]} chips
 * @return {number}
 */
// 所有的奇数都能在代价0的情况下移动到一个点
// 所有的偶都能在代价0的情况下移动到一个点
// 那下面就比较的是 奇数往偶数移动 还是 偶数往奇数移动
var minCostToMoveChips = function(chips) {
    let j = 0, o=0;
    chips.forEach(c=>{
        if(c%2) {o++;}
        else {j++}
    })
    return j>o? o : j;
};

 找出给定方程的正整数解

给出一个函数  f(x, y) 和一个目标结果 z,请你计算方程 f(x,y) == z 所有可能的正整数 数对 x 和 y

给定函数是严格单调的,也就是说:

  • f(x, y) < f(x + 1, y)
  • f(x, y) < f(x, y + 1)

函数接口定义如下:

interface CustomFunction {
public:
  // Returns positive integer f(x, y) for any given positive integer x and y.
  int f(int x, int y);
};

如果你想自定义测试,你可以输入整数 function_id 和一个目标结果 z 作为输入,其中 function_id 表示一个隐藏函数列表中的一个函数编号,题目只会告诉你列表中的 2 个函数。  

你可以将满足条件的 结果数对 按任意顺序返回。

示例 1:

输入:function_id = 1, z = 5
输出:[[1,4],[2,3],[3,2],[4,1]]
解释:function_id = 1 表示 f(x, y) = x + y

示例 2:

输入:function_id = 2, z = 5
输出:[[1,5],[5,1]]
解释:function_id = 2 表示 f(x, y) = x * y

提示:

  • 1 <= function_id <= 9
  • 1 <= z <= 100
  • 题目保证 f(x, y) == z 的解处于 1 <= x, y <= 1000 的范围内。
  • 在 1 <= x, y <= 1000 的前提下,题目保证 f(x, y) 是一个 32 位有符号整数。
/**
 * // This is the CustomFunction's API interface.
 * // You should not implement it, or speculate about its implementation
 * function CustomFunction() {
 *
 *     @param {integer, integer} x, y
 *     @return {integer}
 *     this.f = function(x, y) {
 *         ...
 *     };
 *
 * };
 */
/**
 * @param {CustomFunction} customfunction
 * @param {integer} z
 * @return {integer[][]}
 */
var findSolution = function(customfunction, z) {
    // const result = [];
    // let cY = 1000;
    // for (let i = 1; i < 1000; i++) {
    //     let cZ = customfunction.f(i, cY);
    //     while (cZ > z && cY > 1) {
    //         cY--;
    //         cZ = customfunction.f(i, cY);
    //     }
    //     if (cZ === z) {
    //         result.push([i, cY]);
    //     }
    // }
    // return result;
    // 下面的超出事件限制
    let res = [];
    let x = 1;
    let flag = true;
    for(let y=1; y<=1000; y++){
        if(flag){
            // 题中 1 <= x, y <= 1000,意思是x 和 y 都是这个范围,我开始以为y<=1000,x>=1,它们又都是正整数,所以 1<=y<=1000
            // 导致某种情况,y=xxx, x 就是没有匹配的,x会一直jia,完了就死循环了!!!!!所以才必须加上 cz > z这种情况
            while(x>=1){
              let cz = customfunction.f(x, y);
              if(z===cz){
                  res.push([x, y]);
                  flag = false;
                  break;
                  // 加上下面代码就测试通过了,其实我感觉最大的问题是x你没上限
              } else if(cz>z){
                  flag = false;
                 break;
              }
                x++;
            }    
        } else {
            let x0=x;
            //fnid=2 y =1, x=5  =>  x=4, y=2 ; x=3, y=2; x=2,y=2 ; x=1, y=2(这个可以通过条件毙掉)
             while(--x0 >=1){
                 let cz = customfunction.f(x0, y);
                if(z===cz){
                  res.push([x0, y]);
                    x=x0;
                    break;
                } else if(cz<z) {
                    break;
                }
             } 
        }
    }
    return res
};

  这个题之所以没整出来,

1.理解错题中“处于 1 <= x, y <= 1000 的范围内。”, 写代码的时候,没又把 “

(cz>z)

加上,导致可能有某个测试用例的死循环。

// 下面这个还没搞懂

循环码排列

给你两个整数 n 和 start。你的任务是返回任意 (0,1,2,,...,2^n-1) 的排列 p,并且满足:

  • p[0] = start
  • p[i] 和 p[i+1] 的二进制表示形式只有一位不同
  • p[0] 和 p[2^n -1] 的二进制表示形式也只有一位不同

示例 1:

输入:n = 2, start = 3
输出:[3,2,0,1]
解释:这个排列的二进制表示是 (11,10,00,01)
     所有的相邻元素都有一位是不同的,另一个有效的排列是 [3,1,0,2]

示例 2:

输出:n = 3, start = 2
输出:[2,6,7,5,4,0,1,3]
解释:这个排列的二进制表示是 (010,110,111,101,100,000,001,011)

提示:

  • 1 <= n <= 16
  • 0 <= start < 2^n
/**
 * @param {number} n
 * @param {number} start
 * @return {number[]}
 */
// var replace = function(str, index, replacement){
//     return str.substr(0, index) + replacement+ str.substr(index + replacement.length);
// }
var circularPermutation = function(n, start) {
 const m = Math.pow(2, n);
    const t = [];
    for (let i = 0; i < n; i++) {
        t.push(Math.pow(2, i));
    }
    const c = [];
    for (let i = 0; i < m; i++) {
        c.push(0);
    }
    const result = [ start ];
    c[start] = 1;
    for (let i = 1; i < m; i++) {
        let j = 0;
        while (c[result[i - 1] ^ t[j]]) {
            j++;
        }
        result.push(result[i - 1] ^ t[j]);
        c[result[i - 1] ^ t[j]] = 1;
    }
    return result;
//     let res =[];
//     let start = String(start).toString(2);
//     let arr = start.split('');
//     let end = start;
//     for(let i=0; i<arr.length; i++){
//         if(arr[i]==='0'){
//             end = replace(start, i, '1');
//             replacefn(end,)
//         } else {
//             end=replace(start, i, '0')
//         }
       
//     }
};

  // 其实我的思路是画多叉树,然后递归,感觉是可行的。这个里面他用了二进制异或

替换子串得到平衡字符串

有一个只含有 'Q', 'W', 'E', 'R' 四种字符,且长度为 n 的字符串。

假如在该字符串中,这四个字符都恰好出现 n/4 次,那么它就是一个「平衡字符串」。

给你一个这样的字符串 s,请通过「替换一个子串」的方式,使原字符串 s 变成一个「平衡字符串」。

你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。

请返回待替换子串的最小可能长度。

如果原字符串自身就是一个平衡字符串,则返回 0

示例 1:

输入:s = "QWER"
输出:0
解释:s 已经是平衡的了。

示例 2:

输入:s = "QQWE"
输出:1
解释:我们需要把一个 'Q' 替换成 'R',这样得到的 "RQWE" (或 "QRWE") 是平衡的。

示例 3:

输入:s = "QQQW"
输出:2
解释:我们可以把前面的 "QQ" 替换成 "ER"。 

示例 4:

输入:s = "QQQQ"
输出:3
解释:我们可以替换后 3 个 'Q',使 s = "QWER"。

提示:

  • 1 <= s.length <= 10^5
  • s.length 是 4 的倍数
  • s 中只含有 'Q''W''E''R' 四种字符
/**
 * @param {string} s
 * @return {number}
 */
var balancedString = function(s) {
    // let s1 = {
    //     'Q': 0,
    //     'W':0, 
    //     'E':0, 
    //     'R':0
    // };
    // s.split('').forEach(item=>s1[item]++);
    // let n = s.length/4;
    // let res=0;
    // Object.keys(s1).forEach(item=>{
    //     console.log('item: ',item,'  ',s1[item])
    //     if(s1[item]<n){
    //         res+=(n-s1[item])
    //     }
    // });
    // return res
    // 待替换子串 不是单纯的统计
    const r = [0 , 0, 0, 0];
    const a = {Q : 0, W: 1, E: 2, R: 3};
    for (let i = 0; i < s.length; i++) {
        r[a[s[i]]]++;
    }
    const n = s.length / 4;
    if (r[0] === r[1] && r[1] === r[2] && r[2] === r[3]) return 0;
    let l = 0;
    let m = 100001;
    for (let i = 0; i < s.length; i++) {
        r[a[s[i]]]--;
        while (r[0] <= n && r[1] <=n && r[2] <=n && r[3] <= n) {
            m = Math.min(m, i + 1 - l);
            r[a[s[l]]]++;
            l++;
        }
    }
    return m;
};

  

交换字符使得字符串相同

有两个长度相同的字符串 s1 和 s2,且它们其中 只含有 字符 "x" 和 "y",你需要通过「交换字符」的方式使这两个字符串相同。

每次「交换字符」的时候,你都可以在两个字符串中各选一个字符进行交换。

交换只能发生在两个不同的字符串之间,绝对不能发生在同一个字符串内部。也就是说,我们可以交换 s1[i] 和 s2[j],但不能交换 s1[i] 和 s1[j]

最后,请你返回使 s1 和 s2 相同的最小交换次数,如果没有方法能够使得这两个字符串相同,则返回 -1 。

示例 1:

输入:s1 = "xx", s2 = "yy"
输出:1
解释:
交换 s1[0] 和 s2[1],得到 s1 = "yx",s2 = "yx"。

示例 2:

输入:s1 = "xy", s2 = "yx"
输出:2
解释:
交换 s1[0] 和 s2[0],得到 s1 = "yy",s2 = "xx" 。
交换 s1[0] 和 s2[1],得到 s1 = "xy",s2 = "xy" 。
注意,你不能交换 s1[0] 和 s1[1] 使得 s1 变成 "yx",因为我们只能交换属于两个不同字符串的字符。

示例 3:

输入:s1 = "xx", s2 = "xy"
输出:-1

示例 4:

输入:s1 = "xxyyxyxyxx", s2 = "xyyxyxxxyx"
输出:4

提示:

  • 1 <= s1.length, s2.length <= 1000
  • s1, s2 只包含 'x' 或 'y'
/**
 * @param {string} s1
 * @param {string} s2
 * @return {number}
 */
var minimumSwap = function(s1, s2) {
    let l = 0;
    let r = 0;
    for (let i = 0; i < s1.length; i++) {
        if (s1[i] !== s2[i]) {
            if (s1[i] === 'x') {
                l++;
            } else {
                r++;
            }
        }
    }
    if ((l + r) % 2 === 1) return -1;
    return (l + r) / 2 + (l % 2);
};
 if(s1.length != s2.length) return -1;
        let x=0,y=0;
        for(let i=0;i<s1.length;++i) if(s1[i]=='x') x++;else y++;
        for(let i=0;i<s2.length;++i) if(s2[i]=='x') x++;else y++;
        if(x%2 || y%2) return -1;
        let cnt1=0,cnt2=0;
        for(let i=0;i<s1.length;++i) 
    {
        if(s1[i] != s2[i]) 
        {
            if(s1[i]=='x') cnt1++;
            else cnt2++;
        }
    }
    return parseInt((cnt1+1)/2)+parseInt((cnt2+1)/2);

 

var minimumSwap = function(s, t) {
     let n = s.length;
        
        let x = 0, y = 0;
        for (let i = 0; i < n; ++ i)
        {
            if (s[i] == t[i]) continue;
            if (s[i] == 'x') ++ x; else ++ y;
        }
        if ((x+y)%2 == 1) return -1;
        
        let ret = parseInt(x/2)+ parseInt(y/2);
        x %= 2;
        y %= 2;
        if (x || y) ret += 2;
        return ret;

xy    yy   xy    

yx    xx   xy

xxy  yxy(yy)  xxy(xy)  

yxx  xxx(xx)  xxy(xy)

xyxy  yyxy  yxxy

yxyx  yxxx  yxxy

 这个我当时也在尽力找规律,找了1个半小时也没找到点决定性的规律

var minimumSwap = function(s1, s2) {
    let s = s1+s2;
    let map = new Map();
    let x=0, y=0;
    for(let i=0; i<s.length; i++){
        if('x'===s[i]){
            map.set('x',++x)
        }else {
            map.set('y',++y)
        }
    }
// 个数必须是偶数个
    if(map.get('x')%2 !==0 || map.get('y')%2!==0){
        return -1
    }
    let first=s1[0], flag = true;
    for(let i=1; i<s1.length; i++){
        if(s[i]!==first){
            flag = false
        }
    }
// 都相同的情况,交换次数是len/2
    if(flag) return s1/2;
    let count=0
    if(s1.length)
    
};

统计「优美子数组」

给你一个整数数组 nums 和一个整数 k

如果某个子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」。

请返回这个数组中「优美子数组」的数目。

示例 1:

输入:nums = [1,1,2,1,1], k = 3
输出:2
解释:包含 3 个奇数的子数组是 [1,1,2,1] 和 [1,2,1,1] 。

示例 2:

输入:nums = [2,4,6], k = 1
输出:0
解释:数列中不包含任何奇数,所以不存在优美子数组。

示例 3:

输入:nums = [2,2,2,1,2,2,1,2,2,2], k = 2
输出:16

提示:

  • 1 <= nums.length <= 50000
  • 1 <= nums[i] <= 10^5
  • 1 <= k <= nums.length
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var numberOfSubarrays = function(nums, k) {
    let result = 0;
    let odd = [ -1 ];
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] % 2 === 1) {
            odd.push(i);
            if (odd.length > k + 1) {
                result += (odd[odd.length - 1] - odd[odd.length - 2]) * (odd[odd.length - 1 - k] - odd[odd.length - 2 - k]);
            }
        }
    }
    if (odd.length > k) {
        result += (nums.length - odd[odd.length - 1]) * (odd[odd.length - k] - odd[odd.length -1 - k]);
    }
    return result;
};

  

给你一个 n 行 m 列的矩阵,最开始的时候,每个单元格中的值都是 0

另有一个索引数组 indicesindices[i] = [ri, ci] 中的 ri 和 ci 分别表示指定的行和列(从 0 开始编号)。

你需要将每对 [ri, ci] 指定的行和列上的所有单元格的值加 1

请你在执行完所有 indices 指定的增量操作后,返回矩阵中 「奇数值单元格」 的数目。

示例 1:

输入:n = 2, m = 3, indices = [[0,1],[1,1]]
输出:6
解释:最开始的矩阵是 [[0,0,0],[0,0,0]]。
第一次增量操作后得到 [[1,2,1],[0,1,0]]。
最后的矩阵是 [[1,3,1],[1,3,1]],里面有 6 个奇数。

示例 2:

输入:n = 2, m = 2, indices = [[1,1],[0,0]]
输出:0
解释:最后的矩阵是 [[2,2],[2,2]],里面没有奇数。

提示:

  • 1 <= n <= 50
  • 1 <= m <= 50
  • 1 <= indices.length <= 100
  • 0 <= indices[i][0] < n
  • 0 <= indices[i][1] < m
/**
 * @param {number} n
 * @param {number} m
 * @param {number[][]} indices
 * @return {number}
 */
const flatten = arr => arr.reduce(
    (acc,val) => acc.concat(Array.isArray(val)? flatten(val):val),[]
)
var oddCells = function(n, m, indices) {
    let arr = [];
    let m0=m;
    while(n--){
        let a = [];
        while(m0--){
            a.push(0)
        }
        m0=m;
        arr.push(a)
    };
    indices.forEach(d=>{
        let [r, c] = d;
/*为什么在控制台操作就可以,因为这里是给数据直接赋值。而下面map是返回新数组,forEach虽是循环但你的操作是仅仅是+1的话,
就好比 arr[1] + 1,这个只会返回一个新值,必须重新赋值 arr[1] = arr[1] + 1;类似var a = 1; a+1 与 a = a+1 不同
let a = [[1,2,3],2,3]; a[0][1]=100
100
let arr = [1,2,3]; arr[0]=100
100
        */
        arr[r] = arr[r].map(a=>a+1);
        arr.forEach(a=>a[c] = a[c]+1)
    })
    // return arr.flat().filter(f=>f%2===1).length
    return flatten(arr).filter(f=>f%2===1).length
    
};
原文地址:https://www.cnblogs.com/zhangzs000/p/11567732.html