kong0827 / practise_weekly

每周不定期更新数道算法题,希望自己能够坚持下来,也希望大家能够监督共同进步

Repository from Github https://github.comkong0827/practise_weeklyRepository from Github https://github.comkong0827/practise_weekly

题目汇总

题目一:平均分组问题(Java实现)

题目描述

按分数对选手进行平均分组,可分多组。

注意:

  1. 输入的选手名单players为集合形式,player表示选手名称,score表示选手的分数
  2. 选手的分数体现选手的实力,分数有可能是负数
  3. 最终解不是唯一,但要求分组后,每组的实力尽量接近,每组的人数也尽量接近

例如: 将所有选手,总共7人

[
    {
        "player": "a",
        "score": 22
    },
    {
        "player": "b",
        "score": -9
    },
    {
        "player": "c",
        "score": 13
    },
    {
        "player": "d",
        "score": 17
    },
    {
        "player": "e",
        "score": 0
    },
    {
        "player": "f",
        "score": -11
    },
    {
        "player": "g",
        "score": -2
    }
]

1、如果分成两组,应该是4 VS 3 的队形

[
  [
    {
      "player": "a",
      "score": 22
    },
    {
      "player": "e",
      "score": 0
    },
    {
      "player": "g",
      "score": -2
    },
    {
      "player": "f",
      "score": -11
    }
  ],
  [
    {
      "player": "d",
      "score": 17
    },
    {
      "player": "c",
      "score": 13
    },
    {
      "player": "b",
      "score": -9
    }
  ]
]

2、如果分成三组,应该是3 VS 2 VS 2的队形

[
  [
    {
      "player": "a",
      "score": 22
    },
    {
      "player": "b",
      "score": -9
    },
    {
      "player": "f",
      "score": -11
    }
  ],
  [
    {
      "player": "c",
      "score": 13
    },
    {
      "player": "e",
      "score": 0
    }
  ],
  [
    {
      "player": "d",
      "score": 17
    },
    {
      "player": "g",
      "score": -2
    }
  ]
]

​ 不知道大家第一次看到这代题目时候,是怎么想的。请大家先想一下,不要着急看我的思路和代码,这样容易顺着我的思路走,应该有自己的思路与想法,如果没有,再参考我的解决思路。

解题思路

​ 首先可以确定的是这道题是有可能无法得到最优解的,只能得到一个接近最优解的解或最优解。

  1. 1、 先按照选手的分数按照正序或者倒叙进行排序,我这里按照倒叙排列。

  2. 2、 求出所有选手的总分数,然后求出平均数。

  3. 3、 将选手分成两组,例如组一,组二,然后用组一的分值最小的选手去和组二中分值最大的选手进行交换

  4. 4、如果交换后组一的总分数大于平均数,那么进行交换,直至出现临界值,当组一的总分数小于平均分值,即分组成功

+ 1、<!--要注意分组中负数的存在,负数会越加越小。-->
+ 2、<!--为什么用组一的分值最小的选手去和组二中分值最大的选手进行交换-->

​			 因为可以使组一的分值缓慢下降,直至出现组一的分值大于平均值。 否则快速下降,很难确定临界值。

https://github.com/kong0827/practise_monthly/tree/master/Grouping


题目二:等价多米诺骨牌

给你一个由一些多米诺骨牌组成的列表 dominoes。

如果其中某一张多米诺骨牌可以通过旋转 0 度或 180 度得到另一张多米诺骨牌,我们就认为这两张牌是等价的。

形式上,dominoes[i] = [a, b] 和 dominoes[j] = [c, d] 等价的前提是 ac 且 bd,或是 ad 且 bc。

在 0 <= i < j < dominoes.length 的前提下,找出满足 dominoes[i] 和 dominoes[j] 等价的骨牌对 (i, j) 的数量。

输入:dominoes = [[1,2],[2,1],[3,4],[5,6]]
输出:1

题目三:LRU算法

题目描述

设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。

获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。 写入数据 put(key, value) - 如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。

示例:

LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // 返回  1
cache.put(3, 3);    // 该操作会使得密钥 2 作废
cache.get(2);       // 返回 -1 (未找到)
cache.put(4, 4);    // 该操作会使得密钥 1 作废
cache.get(1);       // 返回 -1 (未找到)
cache.get(3);       // 返回  3
cache.get(4);       // 返回  4

上述示例解释:默认一个LRU的缓存容量是 2

cache.put(1, 1);                       缓存中有为                      1
cache.put(2, 2);                       缓存中为(有先后顺序)             1 ->2      
cache.get(1);                          1被使用,缓存数据数据发生变化      2->1
cache.put(3, 3);                       最大容量为2,因此缓存中2删除       1->3

以此类推.....

About

每周不定期更新数道算法题,希望自己能够坚持下来,也希望大家能够监督共同进步


Languages

Language:Java 100.0%