Remove duplicates from an unsorted linked list. I used ArrayList to solve - arraylist

Given an unsorted linked list of N nodes. The task is to remove duplicate elements from this unsorted Linked List. When a value appears in multiple nodes, the node which appeared first should be kept, all others duplicates are to be removed.
Example 1:
Input:
N = 4
value[] = {5,2,2,4}
Output: 5 2 4
Explanation: Given linked list elements are
5->2->2->4, in which 2 is repeated only.
So, we will delete the extra repeated
elements 2 from the linked list and the
resultant linked list will contain 5->2->4
It's a question on GFG and I passed 405 test cases but on 406th test case it shows 'Time limit exceeded Error'. Is it like ArrayList is taking too long to traverse every element again and again?
Then I tried using HashSet with the same logic and it worked perfectly and passes all test cases.
class Solution
{
//Function to remove duplicates from unsorted linked list.
public Node removeDuplicates(Node head)
{
// Your code here
Node prev = head;
Node temp = head.next;
ArrayList<Integer> val = new ArrayList<>();
val.add(head.data);
while(temp != null){
if(val.contains(temp.data)){
prev.next = temp.next;
temp = temp.next;
}
else{
val.add(temp.data);
temp = temp.next;
prev = prev.next;
}
}
return head;
}
}

While your logic is indeed correct, it is not the most optimal solution.
Consider this example:
Input: 5 -> 2 -> 2 -> 2 -> 2 -> 3
Your Result steps would be:
5 -> 2 -> 2 -> 2 -> 2 -> 3
5 -> 2 -> 2 -> 2 -> 3
5 -> 2 -> 2 -> 3
5 -> 2 -> 3
Instead of doing the pointer writes so many times, you could keep going forward till you encounter the first not-seen-so-far node and make your pointers point to the new node directly.
Moreover, instead of using an ArrayList, you could use a Set. The .contains() method in ArrayList has a time complexity of O(n) where n is the number of elements in the ArrayList. As you do this operation M times for each loop, your order is going to be O(mn). Set has a time complexity of O(1) (Constant lookup time), So if you the do the operation M times, it will be M times O(1) which is whole lot faster.
Perhaps this code might help:
class Solution
{
//Function to remove duplicates from unsorted linked list.
public Node removeDuplicates(Node head)
{
if(head == NULL) { // BASE CASE
return head;
}
Node prev = head;
Node temp = head.next;
boolean shouldDelete = false;
Set<Integer> set = new HashSet<>();
set.add(head.data);
while(temp != null){
if(set.contains(temp.data)){
shouldDelete = true; // Set this to true to make sure any duplicates at the end is also taken care of.
}
else{
shouldDelete = false; // Set this to false as we have encountered a not-seen-so-far node.
set.add(temp.data);
prev.next = temp;
prev = temp;
}
temp = temp.next;
}
if(shouldDelete) { // There is duplicate elements in the end that has not been trimmed because we never encountered a not-seen-so-far element. So set it to NULL
prev.next = NULL;
}
return head;
}
}

Related

print n times number from 1. Need print (1 2 2 3 3 3 4)

I can't figure out how to solve the following problem: there is a number n. Output the numbers to the console in order separated by a space, but so that the next digit in the iteration is output as many times as it is a digit, and at the same time so that there are no more than n digits in the output. Сan anyone suggest the correct algorithm?
example: have n = 7, need print (1 2 2 3 3 3 4) in kotlin
what i try:
var n = 7
var count = 1
var i = 1
for (count in 1..n) {
for (i in 1..count) {
print(count)
}
}
}
var n = 11
var count = 1
var i = 1
var size = 0
// loop# for naming a loop in kotlin and inside another loop we can break or continue from outer loop
loop# for (count in 1..n) {
for (i in 1..count) {
print(count)
size++
if (size == n){
break#loop
}
}
}
You can use "#" for naming loops and if you want to break from that loop, you can use this syntax in kotlin. It worked for me.
For kotlin labeled break you can look at this reference: link
var count = 1
var n = 7
for(count in 1..n) {
print(count.toString().repeat(count))
}
count.toString() converts an integer to a string, .repeat() function repeats count times the string.
In case you need to add a space between each number, you can add the following:
print(" ")
Using generateSequence and Collections functions:
val n = 7
println(generateSequence(1) {it + 1}
.flatMap{e -> List(e){e}}
.take(n)
.joinToString(" "))
Your example is correct, You have to put a space between the printing
you can follow the code from this link
Kotlin lang code snippet
or the following code snippet
fun main() {
var n = 7
var count = 1
var i = 1
for (count in 1..n) {
for (i in 1..count) {
print(count)
print(' ')
}
}
}
For completeness, here's another approach where you write your own sequence function which produces individual values on demand (instead of creating intermediate lists)
sequence {
var digit = 1
while (true) {
for (i in 1..digit) yield(digit)
digit++
}
}.take(7)
.joinToString(" ")
.run(::print)
Not a big deal in this situation, but good to know!

Write a kotlin program that prints the number that is repeated the most in a consecutive way

I'm kind of stuck, I don't know how to make the second loop to start 1 position above the first loop in Kotlin.
I have an array (named myArray) with 10 elements, I need to Write a Kotlin program that prints the number that has the most consecutive repeated number in the array and also prints the number of times it appears in the sequence.
The program must parse the array from left to right so that if two numbers meet the condition, the one that appears first from left to right will be printed.
Longest: 3
Number: 8
fun main() {
val myArray: IntArray = intArrayOf(1,2,2,4,5,6,7,8,8,8)
for((index , value) in myArray.withIndex()){
var inx = index + 1
var count = 0
var longest = 0
var number = 0
for((inx,element) in myArray.withIndex()) {
if(value == element ){
count+=
}
}
if(longest < count){
longest = count
number = value
}
}
}
I'm against just dropping answers, but it is quite late for me, so I'll leave this answer here and edit it tomorrow with more info on how each part works. I hope that maybe in the meanwhile it will help you to gain some idea to where you might be going wrong.
val results = mutableMapOf<Int, Int>()
(0..myArray.size - 2).forEach { index ->
val current = myArray[index]
if (current == myArray[index + 1]) {
results[current] = (results[current] ?: 1) + 1
}
}
val (max, occurrences) = results.maxByOrNull { it.value } ?: run { println("No multiple occurrences"); return }
println("Most common consecutive number $max, with $occurrences occurrences")
Alternatively if the intArray would be a list, or if we allowed to change it to a list myArray.toList(), you could replace the whole forEach loop with a zipWithNext. But I'm pretty sure that this is a HW question, so I doubt this is the expected way of solving it.
myList.zipWithNext { a, b ->
if (a == b) results[a] = (results[a] ?: 1) + 1
}

My take on Migratory Bird is failing one case

Update: I completely overlooked the complexity added by arr.sort() method. So in Kotlin for array of Int, It compiles to use java.util.DualPivotQuicksort see this which in turn has complexity of O(n^2). see this. Other than that, this is also a valid approach.
I know It can be solved by keeping multiple arrays or using collections (which is what I ended up submitting), I want to know what I missed in the following approach
fun migratoryBirds(arr: Array<Int>): Int {
var maxCount = 0
var maxType = 0
var count = 0
var type = 0
arr.sort()
println(arr.joinToString(" "))
for (value in arr){
if (type != value){
if (count > maxCount){
maxCount = count
maxType = type
}
// new count values
type = value
count = 1
} else {
count++
}
}
return maxType
}
This code passes every scenario except for Test case 2 which has 73966 items for array. On my local machine, that array of 73k+ elements was causing timeout but I did test for array up-to 20k+ randomly generated value 1..5 and every time it succeeded. But I couldn't manage to pass Test case 2 with this approach. So even though I ended up submitting an answer with collection stream approach, I would really like to know what could I be missing in above logic.
I am running array loop only once Complexity should be O(n), So that could not be reason for failing. I am pre-sorting array in ascending order, and I am checking for > not >=, therefore, If two types end up having same count, It will still return the lower of the two types. And this approach is working correctly even for array of 20k+ elements ( I am getting timeout for anything above 25k elements).
The reason it is failing is this line
arr.sort()
Sorting an array takes O(n logn) time. However using something like a hash map this can be solved in O(n) time.
Here is a quick python solution I made to give you the general idea
# Complete the migratoryBirds function below.
def migratoryBirds(arr):
ans = -1
count = -1
dic = {}
for x in arr:
if x in dic:
dic[x] += 1
else:
dic[x] = 1
if dic[x] > count or dic[x] == count and x < ans:
ans = x
count = dic[x]
return ans

Deleting the maximum element in BST

Some of the code below seems too obvious, traversing the tree using its right most branch since that is where all the max values are.However, I don't understand a few things about this code I saw in Robert Sedgewick's Algorithms book.
public void deleteMax() {
if (isEmpty()) throw new NoSuchElementException("");
root = deleteMax(root);
assert check();
}
private Node deleteMax(Node x) {
if (x.right == null) return x.left;
x.right = deleteMax(x.right);
x.size = size(x.left) + size(x.right) + 1;
return x;
}
In the private method why do we return the left element if the right child of x is null ?From my understanding x would be the maximum if x has no right children and is the right most node we could go to.Also I don't understand when do we return x in the last line of the 2nd method.
If x doesn't have a right child then x is the maximum node. We "delete" it by returning x.left (the new max node). We return x after we've modified its right subtree.

ZSCAN guarantee for elements which score has changed during iteration

I cannot find this information in the documentation: Does Redis guarantee that an element is returned with ZSCAN command under this condition:
The element was contained in the sorted set from the start to the end
of a full iteration, BUT the score of such element has changed (even
several times, for instance by another client) during iteration?
Only related statement I found regarding this is the following:
Elements that were not constantly present in the collection during a
full iteration, may be returned or not: it is undefined.
But I don't know if score change in such case is the same thing as remove/add operations or not.
If the element exists during the full iteration, it will be returned by the zscan command. It doesn't matter whether the score has been changed during the iteration.
Normally, zset is implemented as a hash table (i.e. Redis' dict), and a skiplist. When running the zscan command, it iterates over the hash table entries to do the scan job. The changing of the score (value of the dict entry) won't affect the iteration process.
If zset is small enough, Redis implements it as a ziplist. In this case, Redis returns all elements in a single zscan call. So the score CANNOT be changed during the iteration.
In a word, you have the guarantee.
Thanks a lot for_stack for the confirmation. I didn't know if someone will response so meanwhile I implemented some own checks in Java:
#Test
public void testZScanGuaranteeWithScoreUpdates() {
try (Jedis jedis = jedisPool.getResource()) {
IntStream.rangeClosed(1, 50).forEach(i -> testZScanGuaranteeWithUpdates(jedis, false));
IntStream.rangeClosed(1, 50).forEach(i -> testZScanGuaranteeWithUpdates(jedis, true));
}
}
/**
* Changing score of elements (named ids) during iteration (eventually inserting and removing another unchecked ids)
* and then assert that no element (id) is missing
*/
private void testZScanGuaranteeWithUpdates(Jedis jedis, boolean noise) {
Random ran = new Random();
List<String> noiseIds = IntStream.range(0, 4000).mapToObj(i -> UUID.randomUUID().toString()).collect(toList());
if (noise) { // insert some noise with random score (from 0 to 5000)
noiseIds.forEach(id -> jedis.zadd(KEY, ran.nextInt(5000), id));
}
int totalIds = 2000;
List<String> ids = IntStream.range(0, totalIds).mapToObj(i -> UUID.randomUUID().toString()).collect(toList());
Set<String> allScanned = new HashSet<>();
ids.forEach(id -> jedis.zadd(KEY, ran.nextInt(2500) + 1000, id)); // insert all IDs with random score (from 1000 to 3500)
redis.scanIds(KEY, 100, res -> { // encapsulate iteration step - this closure is executed for every 100 elements during iteration
allScanned.addAll(res); // record 100 scanned ids
Collections.shuffle(ids);
ids.stream().limit(500).forEach(id -> jedis.zadd(KEY, ran.nextInt(2500) + 1000, id)); // change score of 500 random ids
if (noise) { // insert and remove some noise
IntStream.range(0, 50).forEach(i -> jedis.zadd(KEY, ran.nextInt(5000), UUID.randomUUID().toString()));
IntStream.range(0, 60).forEach(i -> jedis.zrem(KEY, noiseIds.get(ran.nextInt(noiseIds.size()))));
}
});
if (!noise) {
assertEquals(totalIds, allScanned.size()); // 2000 unique ids scanned
}
assertTrue(allScanned.containsAll(ids)); // none id is missing
jedis.del(KEY); // prepare for test re-execution
}
Tests are passing, i.e. all elements are returned by ZSCAN even when their score has changed during iteration using ZADD command.