我有以下问题:
您将获得N个计数器,最初设置为0,您可以对它们进行两种操作:
给出了M个整数的非空零索引数组A.此数组表示连续操作:
例如,给定整数N = 5且数组A使得:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
每次连续操作后计数器的值为:
(0, 0, 1, 0, 0)
(0, 0, 1, 1, 0)
(0, 0, 1, 2, 0)
(2, 2, 2, 2, 2)
(3, 2, 2, 2, 2)
(3, 2, 2, 3, 2)
(3, 2, 2, 4, 2)
目标是在所有操作之后计算每个计数器的值。
我做了以下解决方案,但它在O(NK)处运行,其中K =阵列A的长度。
public int[] solution(int N, int[] A) {
int[] result = new int[N];
int maximum = 0;
for (int K = 0; K < A.Length; K++)
{
if (A[K] < 1 || A[K] > N + 1)
throw new InvalidOperationException();
if (A[K] >= 1 && A[K] <= N)
{
result[A[K] - 1]++;
if (result[A[K] - 1] > maximum)
{
maximum = result[A[K] - 1];
}
}
else
{
// inefficiency here
for (int i = 0; i < result.Length; i++)
result[i] = maximum;
}
}
return result;
}
有人能告诉我如何用O(N + K)做得更好,其中K是数组A的长度吗?很抱歉可能编码很糟糕,我正在做这些练习来改进我的编程。谢谢!
答案 0 :(得分:14)
这就是我想出来的,但我不确定它是否100%有效:
public int[] solution(int N, int[] A) {
int[] result = new int[N];
int maximum = 0;
int resetLimit = 0;
for (int K = 0; K < A.Length; K++)
{
if (A[K] < 1 || A[K] > N + 1)
throw new InvalidOperationException();
if (A[K] >= 1 && A[K] <= N)
{
if (result[A[K] - 1] < resetLimit) {
result[A[K] - 1] = resetLimit + 1;
} else {
result[A[K] - 1]++;
}
if (result[A[K] - 1] > maximum)
{
maximum = result[A[K] - 1];
}
}
else
{
// inefficiency here
//for (int i = 0; i < result.Length; i++)
// result[i] = maximum;
resetLimit = maximum;
}
}
for (int i = 0; i < result.Length; i++)
result[i] = Math.Max(resetLimit, result[i]);
return result;
}
答案 1 :(得分:4)
记住:
&#34;使您的代码可读与使其可执行一样重要。&#34;
- Robert C Martin
即使在尝试解决难题时......
因此,为了获得更好的可读性,我创建了一个类来封装计数器数组及其操作(Law of Demeter)。可悲的是,我的第一个解决方案在性能测试中只获得了60%,所以以一点可读性为代价,我通过更智能的解决方案改进了它,最终得到了100%。
以下是我的两个带注释的实现:
//I didn't refactored the names of the variables N and A
//to maintain it aligned with the question description
public int[] solution(int N, int[] A)
{
var counters = new Counters(N);
for (int k = 0; k < A.Length; k++)
{
if (A[k] <= N)
counters.IncreaseCounter(A[k]);
else
counters.MaxAllCounters();
}
return counters.ToArray();
}
public class Counters
{
private int[] counters;
private int greaterValueInCounter = 0;
public Counters(int length)
{
counters = new int[length];
}
public void MaxAllCounters()
{
for (int i = 0; i < counters.Length; i++)
{
counters[i] = greaterValueInCounter;
}
}
public void IncreaseCounter(int counterPosition)
{
//The counter is one-based, but our array is zero-based
counterPosition--;
//Increments the counter
counters[counterPosition]++;
if (counters[counterPosition] > greaterValueInCounter)
greaterValueInCounter = counters[counterPosition];
}
//The counters array is encapsuled in this class so if we provide external
//acess to it anyone could modify it and break the purpose of the encapsulation
//So we just exposes a copy of it :)
public int[] ToArray()
{
return (int[])counters.Clone();
}
}
请注意封装的美妙之处:为了改进算法,我只需编辑Counters
类的某些方法,而无需更改solution
方法上的单个字符。
在Counters
课程中编辑的方法:
IncreaseCounter()
MaxAllCounters()
ToArray()
最终代码:
//Exactly the same code
public int[] solution(int N, int[] A)
{
var counters = new Counters(N);
for (int k = 0; k < A.Length; k++)
{
if (A[k] <= N)
counters.IncreaseCounter(A[k]);
else
counters.MaxAllCounters();
}
return counters.ToArray();
}
public class Counters
{
private int[] counters;
private int greaterValueInCounter = 0;
private int currentEquilibratedScore = 0;
public Counters(int length)
{
counters = new int[length];
}
public void MaxAllCounters()
{
//We don't update the entire array anymore - that was what caused the O(N*M)
//We just save the current equilibrated score value
currentEquilibratedScore = greaterValueInCounter;
}
public void IncreaseCounter(int counterPosition)
{
//The counter is one-based, but our array is zero-based
counterPosition--;
//We need to add this "if" here because with this new solution the array
//is not always updated, so if we detect that this position is lower than
//the currentEquilibratedScore, we update it before any operation
if (counters[counterPosition] < currentEquilibratedScore)
counters[counterPosition] = currentEquilibratedScore + 1;
else
counters[counterPosition]++;
if (counters[counterPosition] > greaterValueInCounter)
greaterValueInCounter = counters[counterPosition];
}
//The counters array is encapsuled in this class so if we provide external
//acess to it anyone could modify it and break the purpose of the encapsulation
//So we just exposes a copy of it :)
public int[] ToArray()
{
//Now we need to fix the unupdated values in the array
//(the values that are less than the equilibrated score)
for (int i = 0; i < counters.Length; i++)
{
if (counters[i] < currentEquilibratedScore)
counters[i] = currentEquilibratedScore;
}
return (int[])counters.Clone();
}
}
答案 2 :(得分:3)
def solution(N, A):
# write your code in Python 2.6
res = [0] * N
m = 0
minValue = 0
for x in A:
if 1 <= x <= N:
res[x - 1] = max(res[x - 1], minValue) + 1
if res[x - 1] > m:
m = res[x - 1]
else:
minValue = m
for i in xrange(N):
res[i] = max(res[i], minValue)
return res
答案 3 :(得分:3)
这是我在Python中提出的解决方案(100/100关于codility);它与我在这里看到的其他人有点不同,所以我想分享:
def solution(N, A):
count = [0] * N
max_counter = [i for i, a in enumerate(A) if a == N+1]
if len(max_counter) == len(A):
return count
if max_counter:
mode = 0
for i, m in enumerate(max_counter):
if m == 0 or m - max_counter[i-1] == 1:
continue
subcount = {}
if i == 0:
for k in A[:m]:
if k not in subcount:
subcount[k] = 1
else:
subcount[k] += 1
else:
for k in A[max_counter[i-1]+1:m]:
if k not in subcount:
subcount[k] = 1
else:
subcount[k] += 1
mode += max(subcount.values())
count = [mode] * N
for k in A[max_counter[-1]+1:]:
count[k-1] += 1
else:
for k in A:
count[k-1] += 1
return count
答案 4 :(得分:1)
让我们看看......
public int[] Solution(int N, int[] A)
{
int[] data = new int[N];
int maxval = 0;
int baseval = 0;
for (int K = 0; K < A.length; K++)
{
int index = A[K] - 1;
if (index < 0 || index > N)
throw new InvalidOperationException();
if (index < N)
maxval = baseval + Math.Max(maxval, ++data[index]);
else
{
baseval = maxval;
data = new int[N];
}
}
for (int K = 0; K < N; K++)
data[K] += baseval;
return data;
}
我认为那是O(N+K)
。取决于您如何计算重新初始化数组的顺序。
答案 5 :(得分:1)
这是PHP的实现:
function solution($N, $A) {
$output = array_fill(0, $N, 0);
$maxCounter = 0;
$minCounter = 0;
foreach ($A as $number) {
if($number === $N + 1) {
$minCounter = $maxCounter;
} else if($number <= $N) {
$number--;
if($minCounter > $output[$number]) {
$output[$number] = $minCounter;
}
$output[$number]++;
if($output[$number] > $maxCounter) $maxCounter = $output[$number];
}
}
foreach ($output as $index => $number) {
if($number < $minCounter) $output[$index] = $minCounter;
}
// var_dump($output);
return $output;
}
答案 6 :(得分:1)
快速解决方案100%
public func solution(_ N : Int, _ A : inout [Int]) -> [Int] {
// write your code in Swift 4.2.1 (Linux)
var solution = Array.init(repeating: 0, count: N)
var max = 0
var actualMaxValue = 0
for obj in A {
if (obj <= N && obj >= 1 ) {
if solution[obj-1] < actualMaxValue {
solution [obj-1] = actualMaxValue + 1
} else {
solution[obj-1] += 1
}
if (solution[obj-1] > max) {
max = solution[obj-1]
}
}
else if obj == N+1 {
actualMaxValue = max
}
}
for (index, value) in solution.enumerated() {
if value < actualMaxValue {
solution[index] = actualMaxValue
}
}
return solution
}
答案 7 :(得分:1)
与每个人100%得分的原则相同,只是我发现这个版本更容易阅读(而且可能只是因为我写了它)。
using System;
using System.Linq;
class Solution
{
public int[] solution(int N, int[] A)
{
var currentMax = 0;
var resetValue = 0;
var counters = Enumerable.Range(1, N).ToDictionary(i => i, i => 0);
foreach (var a in A)
{
if (a == N + 1) resetValue = currentMax;
else
{
counters[a] = Math.Max(counters[a], resetValue) + 1;
currentMax = Math.Max(currentMax, counters[a]);
}
}
return counters.Values.Select(v => Math.Max(v,resetValue)).ToArray();
}
}
答案 8 :(得分:0)
C ++ 11代码:
Object.prototype.removeItem = function (key, value) {
if (value == undefined)
return;
for (var i in this) {
if (this[i][key] == value) {
this.splice(i, 1);
}
}
};
var collection = [
{ id: "5f299a5d-7793-47be-a827-bca227dbef95", title: "one" },
{ id: "87353080-8f49-46b9-9281-162a41ddb8df", title: "two" },
{ id: "a1af832c-9028-4690-9793-d623ecc75a95", title: "three" }
];
collection.removeItem("id", "87353080-8f49-46b9-9281-162a41ddb8df");
答案 9 :(得分:0)
这是Scala版本,100%关于codility:
import java.util
def solution(N: Int, A: Array[Int]): Array[Int] = {
var counters = new Array[Int](N)
var maxCounter = 0
for(ind <- 0 to A.length-1){
if(A(ind) == (N+1)){
//all to max
util.Arrays.fill(counters,maxCounter)
}else{
//ind -1 cause array index start with 0 which is marked as 1 in the input data
counters(A(ind)-1) += 1
//update max counter if necessary
if(maxCounter< (counters(A(ind)-1))) maxCounter = (counters(A(ind)-1))
}
}
return counters
}
答案 10 :(得分:0)
Ruby Codility Code获得100/100
def solution(a)
if a.length < 3
0
end
a.sort!
for i in 2..a.length - 1
if (a[i-2] + a[i-1]) > a[i]
return 1
end
end
0
end
答案 11 :(得分:0)
街, 我刚刚在本地运行。自己看了看柜台。我使用了这个算法:
public int[] solution(int N, int[] A)
{
int[] result = new int[N];
int maximum = 0;
int resetlimit = 0;
for (int K = 0; K < A.Length; K++)
{
if (A[K] < 1 || A[K] > N + 1)
{
throw new InvalidOperationException();
}
if (A[K] >= 1 && A[K] <= N)
{
if (result[A[K] - 1] < resetlimit)
{
result[A[K] - 1] = resetlimit + 1;
}
else
{
result[A[K] - 1]++;
}
if (result[A[K] - 1] > maximum)
{
maximum = result[A[K] - 1];
}
}
else
{
resetlimit = maximum;
result = Enumerable.Repeat(maximum, result.Length).ToArray();
}
}
//for (int i = 0; i < result.Length; i++)
//{
// result[i] = Math.Max(resetlimit, result[i]);
//}
return result;
}
}
查看问题和结果集,您必须在else语句中包含低效的for循环。外部的for循环不会复制第二个操作
•如果A [K] = N + 1,则操作K为max_counter。
为了迭代A [3] = 6,将结果[]全部设置为&#39; 2&#39;您必须使用最大计数器加载结果数组。否则,您的返回将永远不会有(2,2,2,2,2),如第四个示例数组所示。
我也必须参加考试才能获得我梦寐以求的工作,因此这里效率低下很重要;
声明
result = Enumerable.Repeat(maximum, result.Length).ToArray();
一次性加载数组,因此没有内循环,也没有内部效率。我认为这非常接近正确的结果集。我很惊讶他们没有要求像总回报的锯齿状回归那样回归。尽管如此,这种贪婪测试让我很害怕。
答案 12 :(得分:0)
Ruby 100%
def solution(n, a)
max = 0
offsets = a.inject(Hash.new(max)) do |acc, el|
next Hash.new(max) if el == n+1
acc[el] +=1
max = acc[el] if max < acc[el]
acc
end
(1..n).map{|i| offsets[i]}
end
答案 13 :(得分:0)
这是kotlin版本,100%的可比性
fun solutionMissingInteger(N: Int, A: IntArray): IntArray {
val counters = IntArray(N)
var max = 0
var lastUpdate = 0
for (index in A.indices) {
val element = A[index]
if (element == N + 1) {
lastUpdate = max
} else {
val position = element - 1
if (counters[position] < lastUpdate) {
counters[position] = lastUpdate + 1
} else {
counters[position] = counters[position] +1
}
if (counters[position] > max) {
max = counters[position]
}
}
}
setAllCountersToMaxValue(lastUpdate, counters)
return counters
}
private fun setAllCountersToMaxValue(lastUpdate: Int, counters: IntArray) {
for (index in counters.indices) {
if (counters[index] < lastUpdate)
counters[index] = lastUpdate
}
}
答案 14 :(得分:0)
我可以得到的js最高分数是77%
有什么改善吗?
final List<Participants> participants = await cargarParticipants(param1, param2);
ListView.builder(
itemCount: participants.length,
itemBuilder: (BuildContext context, int index) {
return Container(
child: Center(child: Text('${participants[index].Apellido}')),
);
}
);
答案 15 :(得分:0)
Java,100%/ 100%
public int[] solution(int N, int[] A) {
int[] counters = new int[N];
int currentMax = 0;
int sumOfMaxCounters = 0;
boolean justDoneMaxCounter = false;
for (int i = 0; i < A.length ; i++) {
if (A[i] <= N) {
justDoneMaxCounter = false;
counters[A[i]-1]++;
currentMax = currentMax < counters[A[i]-1] ? counters[A[i]-1] : currentMax;
}else if (!justDoneMaxCounter){
sumOfMaxCounters += currentMax;
currentMax = 0;
counters = new int[N];
justDoneMaxCounter = true;
}
}
for (int j = 0; j < counters.length; j++) {
counters[j] = counters[j] + sumOfMaxCounters;
}
return counters;
}
答案 16 :(得分:0)
php中的100/100解决方案
function solution($N, $A){
$cond = $N + 1;
$cur_max = 0;
$last_upd = 0;
$cnt_arr = array();
$cnt = count($A);
for($i = 0; $i < $cnt; $i++){
$cur = $A[$i];
if($cur == $cond){
$last_upd = $cur_max;
}
else{
$pos = $cur - 1;
if(!isset($cnt_arr[$pos])){
$cnt_arr[$pos] = 0;
}
if($cnt_arr[$pos] < $last_upd){
$cnt_arr[$pos] = $last_upd + 1;
}
else{
$cnt_arr[$pos] ++;
}
if($cnt_arr[$pos] > $cur_max){
$cur_max = $cnt_arr[$pos];
}
}
}
for($i = 0; $i < $N; $i++){
if(!isset($cnt_arr[$i])){
$cnt_arr[$i] = 0;
}
if($cnt_arr[$i] < $last_upd){
$cnt_arr[$i] = $last_upd;
}
}
return $cnt_arr;
}
答案 17 :(得分:0)
100%JavaScript解决方案
function solution(N, A) {
// initialize all counters to 0
let counters = Array(N).fill(0)
// The maximum value of the counter is 0
let max = 0
// This variable will determine if an increment all operation has been encountered
// and its value determines the maximum increment all operation encountered so far
// for start it is 0, and we will set it to the value of max when A[i] == N + 1
let max_all = 0
for(let i = 0; i < A.length; i++) {
if(A[i] <= counters.length) {
// if the value of A[i] is 1, we have to increment c[0]
// and hence the following index
const c_index = A[i] - 1
// if max all operation was found previously,
// we have to set it here, because we are not setting anything in the else section
// we are just setting a flag in the else section
// if its value however is greater than max_all, it probably was already maxed
// and later incremented, therefore we will skip it
if(counters[c_index] < max_all) counters[c_index] = max_all
// do the increment here
const v = ++counters[c_index]
// update the max if the current value is max
max = v > max ? v : max
}
// this is straight forward
else max_all = max
}
// if there are remaining items that have not been set to max_all inside the loop
// we will update them here.
// and we are updating them here instead of inside the for loop in the else section
// to make the running time better. If updated inside the loop, we will have a running time of M * N
// however here it's something like (M + N) ~ O(N)
if(max_all) counters = counters.map(v => v < max_all ? max_all : v)
// return the counters
return counters
}
答案 18 :(得分:0)
ES6
const solution = (n, a) => {
// Initialize to zero
let counter = new Array(n);
for(let i = 0 ; i < n ; i++ ){
counter[i] = 0;
}
let max = 0;
for(let j = 0 ; j < a.length ; j++ ){
const item = a[j];
if( item > n) {
for(let i = 0 ; i < n ; i++ ){
counter[i] = max;
}
}
else{
counter[item-1]++;
if(max < counter[item-1])
{
max = counter[item-1];
}
}
}
return counter;
};
答案 19 :(得分:0)
public int[] counters(int N, int[] A)
{
int[] count = new int[N];
int maxCount = 0;
int setAll = 0;
for (int i = 0; i < A.Length; i++)
{
if (A[i] == N + 1)
{
setAll += maxCount;
maxCount = 0;
count = new int[N];
}
else
{
count[A[i] - 1] += 1;
if (count[A[i] - 1] > maxCount)
{
maxCount = count[A[i] - 1];
}
}
}
for (int j = 0; j < count.Length; j++)
{
count[j] += setAll;
}
return count;
}
我认为这是O(N + K),但是代表性是O(N * K)?如果有人能解释哪个是正确的,我将不胜感激......
答案 20 :(得分:-1)
def solution(N, A):
res = [0] * N
maxV, minV = 0, 0
for x in A:
if 1 <= x <= N:
res[x-1] = max(res[x-1], minV) + 1
maxV = max(maxV, res[x-1])
else: minV = maxV
for i in range(N):
res[i] = max(res[i], minV)
return res