[algorithm learning] sword finger Offer II 042. Number of recent requests (Java / C / C + + / Python / go / trust)

Posted by omegared on Tue, 02 Nov 2021 16:02:57 +0100

Thank you very much for reading this article~
Welcome[ 👍 [like][ ⭐ Collection][ 📝 [comments]~
It's not hard to give up, but it must be cool to insist~
I hope all of us can make a little progress every day~
This paper consists of The white hat of the second leader https://le-yi.blog.csdn.net/ Blog originality~

Sword finger Offer II 042. Recent requests:

Write a RecentCounter class to calculate the most recent requests within a specific time range.

Please implement RecentCounter class:

  • RecentCounter() initializes the counter, and the number of requests is 0.
  • int ping(int t) adds a new request at time t, where T represents a time in milliseconds and returns the number of all requests (including new requests) that have occurred in the past 3000 milliseconds. Specifically, returns the number of requests that occurred within [t-3000, t].

Ensure that each call to ping uses a larger t value than before.

Example 1

Input:
	inputs = ["RecentCounter", "ping", "ping", "ping", "ping"]
	inputs = [[], [1], [100], [3001], [3002]]
Output:
	[null, 1, 2, 3, 3]

Explanation:
	RecentCounter recentCounter = new RecentCounter();
	recentCounter.ping(1);     // requests = [1], range [- 2999,1], return 1
	recentCounter.ping(100);   // requests = [1, 100], range [- 2900100], return 2
	recentCounter.ping(3001);  // requests = [1, 100, 3001], the range is [13001], and 3 is returned
	recentCounter.ping(3002);  // requests = [1, 100, 3001, 3002], the range is [23002], and 3 is returned

Tips

  • 1 <= t <= 109
  • Ensure that the t value used for each ping call is strictly incremented
  • The ping method can be called up to 104 times

analysis

  • The second leader thinks that this algorithm problem has relatively high degrees of freedom.
  • As stipulated in Article 2 of the prompt, the T value used for each Ping call is strictly increased, so the queue can be used. If the difference between the current T and the latest t is more than 3000, it can be cleared. Just go out of the queue in order. There are only 3000 elements in the queue at most, that is, the worst of each Ping is no more than 3000 times out of the queue, The value left by the queue is exactly the return value of the ping method.
  • As stipulated in Article 3 of the prompt, the maximum number of ping calls has been known. If a randomly accessible data structure is used, binary search can also be used. The time complexity will be better than queuing in order. However, if the number of ping is not certain, it is better to use a queue.

Problem solution

java

The built-in binary search is not used because it is not a negative number and is not the value we want.

class RecentCounter {
    private int[] q;
    private int head;
    private int tail;

    public RecentCounter() {
        q = new int[10000];
    }

    public int ping(int t) {
        head = binarySearch(q, head, tail, t - 3000);
        q[tail++] = t;
        return tail - head;
    }

    private int binarySearch(int[] a, int fromIndex, int toIndex, int key) {
        int low  = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid    = (low + high) >>> 1;
            int midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return low;  // key not found.
    }
}

c

typedef struct {
    int *q;
    int head;
    int tail;
} RecentCounter;


RecentCounter *recentCounterCreate() {
    RecentCounter *recentCounter = (RecentCounter *) malloc(sizeof(RecentCounter));
    recentCounter->q = (int *) malloc(sizeof(int) * 10000);
    recentCounter->head = 0;
    recentCounter->tail = 0;
    return recentCounter;
}

int binarySearch(int *a, int fromIndex, int toIndex, int key) {
    int low = fromIndex;
    int high = toIndex - 1;

    while (low <= high) {
        int mid = (low + high) >> 1;
        int midVal = a[mid];

        if (midVal < key)
            low = mid + 1;
        else if (midVal > key)
            high = mid - 1;
        else
            return mid; // key found
    }
    return low;  // key not found.
}

int recentCounterPing(RecentCounter *obj, int t) {
    obj->head = binarySearch(obj->q, obj->head, obj->tail, t - 3000);
    obj->q[obj->tail++] = t;
    return obj->tail - obj->head;
}

void recentCounterFree(RecentCounter *obj) {
    free(obj->q);
    free(obj);
}

c++

class RecentCounter {
private:
    vector<int> q;
    int head;
public:
    RecentCounter() {
        head = 0;
    }

    int binarySearch(vector<int>& a, int fromIndex, int toIndex, int key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >> 1;
            int midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return low;  // key not found.
    }

    int ping(int t) {
        head = binarySearch(q, head, q.size(), t - 3000);
        q.push_back(t);
        return q.size() - head;
    }
};

python

python is the most concise this time. It mainly has binary search that can be used directly.

class RecentCounter:

    def __init__(self):
        self.q = []
        self.head = 0

    def ping(self, t: int) -> int:
        self.head = bisect.bisect_left(self.q, t - 3000, self.head)
        self.q.append(t)
        return len(self.q) - self.head

go

type RecentCounter struct {
	q    []int
	head int
}

func Constructor() RecentCounter {
	return RecentCounter{[]int{}, 0}
}

func (this *RecentCounter) Ping(t int) int {
	this.head = binarySearch(this.q, this.head, len(this.q), t - 3000)
	this.q = append(this.q, t)
	return len(this.q) - this.head
}

func binarySearch(a []int, fromIndex int, toIndex int, key int) int {
	low := fromIndex
	high := toIndex - 1

	for low <= high {
		mid := (low + high) >> 1
		midVal := a[mid]

		if midVal < key {
			low = mid + 1
		} else if midVal > key {
			high = mid - 1
		} else {
			return mid // key found
		}
	}
	return low // key not found.
}

rust

struct RecentCounter {
  q: Vec<i32>,
  head: i32,
}


/**
 * `&self` means the method takes an immutable reference.
 * If you need a mutable reference, change it to `&mut self` instead.
 */
impl RecentCounter {
  fn new() -> Self {
    RecentCounter { q: Vec::new(), head: 0 }
  }

  fn ping(&mut self, t: i32) -> i32 {
    self.head = RecentCounter::binarySearch(&self.q, self.head, self.q.len() as i32, t - 3000);
    self.q.push(t);
    self.q.len() as i32 - self.head
  }

  fn binarySearch(a: &Vec<i32>, fromIndex: i32, toIndex: i32, key: i32) -> i32 {
    let mut low = fromIndex;
    let mut high = toIndex - 1;

    while low <= high {
      let mid = (low + high) >> 1;
      let midVal = a[mid as usize];

      if midVal < key {
        low = mid + 1;
      } else if midVal > key {
        high = mid - 1;
      } else {
        return mid; // key found
      }
    }
    return low;  // key not found.
  }
}

Original title portal: https://leetcode-cn.com/problems/H8086Q/

Topics: Python Java C Go Rust