Skip to content

Commit

Permalink
Fix array plus one v3 (keon#432)
Browse files Browse the repository at this point in the history
* Fixes code for linkedlist/copy_random_pointer

  - Fixes the code (was previously commented) by uncommenting it and
  implementing the missing class that was referenced
  - Creates 2 test cases for both solutions in the code

* Fix tests for arrays/plus_one

  - There was an issue while trying to access an index in a for loop
  within the array package (plus_one_v3() function)
    - idx was a tuple since it was being created as an enumerate(list)
    but it was being used as a simple index to access the list.
    - Changes the idx to access the element of the tuple that is the
    actual index (not the value)

* Reformat linkedlist copy_random_pointer

  - Remove classes. Now there are 2 versions of the same function
  - Remove tests.
    - Move tests to the tests directory. Since the structure of this
    node is slightly different (adding an atribute) there is a helper
    inner function that will create the nodes in the structure for the 2
    tests that were added.

* Unify name of functions in copy_random_pointer.py
  • Loading branch information
krimvp authored and keon committed Oct 16, 2018
1 parent bac3222 commit 8694de5
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 36 deletions.
4 changes: 2 additions & 2 deletions algorithms/arrays/plus_one.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def plus_one_v2(digits):
def plus_one_v3(num_arr):

for idx in reversed(list(enumerate(num_arr))):
num_arr[idx] = (num_arr[idx] + 1) % 10
if num_arr[idx]:
num_arr[idx[0]] = (num_arr[idx[0]] + 1) % 10
if num_arr[idx[0]]:
return num_arr
return [1] + num_arr
1 change: 1 addition & 0 deletions algorithms/linkedlist/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
from .is_cyclic import *
from .merge_two_list import *
from .is_palindrome import *
from .copy_random_pointer import *
72 changes: 41 additions & 31 deletions algorithms/linkedlist/copy_random_pointer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,45 @@
Return a deep copy of the list.
"""
# from collections import defaultdict
from collections import defaultdict

# TODO: This requires to be rewritten -- commenting it out for now
# class Solution0:
# @param head, a RandomListNode
# @return a RandomListNode
# def copyRandomList(self, head):
# dic = dict()
# m = n = head
# while m:
# dic[m] = RandomListNode(m.label)
# m = m.next
# while n:
# dic[n].next = dic.get(n.next)
# dic[n].random = dic.get(n.random)
# n = n.next
# return dic.get(head)
#
#
# class Solution1: # O(n)
# @param head, a RandomListNode
# @return a RandomListNode
# def copyRandomList(self, head):
# copy = defaultdict(lambda: RandomListNode(0))
# copy[None] = None
# node = head
# while node:
# copy[node].label = node.label
# copy[node].next = copy[node.next]
# copy[node].random = copy[node.random]
# node = node.next
# return copy[head]

class RandomListNode(object):
def __init__(self, label):
self.label = label
self.next = None
self.random = None


def copy_random_pointer_v1(head):
"""
:type head: RandomListNode
:rtype: RandomListNode
"""
dic = dict()
m = n = head
while m:
dic[m] = RandomListNode(m.label)
m = m.next
while n:
dic[n].next = dic.get(n.next)
dic[n].random = dic.get(n.random)
n = n.next
return dic.get(head)


# O(n)
def copy_random_pointer_v2(head):
"""
:type head: RandomListNode
:rtype: RandomListNode
"""
copy = defaultdict(lambda: RandomListNode(0))
copy[None] = None
node = head
while node:
copy[node].label = node.label
copy[node].next = copy[node.next]
copy[node].random = copy[node.random]
node = node.next
return copy[head]
47 changes: 44 additions & 3 deletions tests/test_linkedlist.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import unittest

from algorithms.linkedlist import (
reverse_list, reverse_list_recursive,
is_sorted,
Expand All @@ -6,16 +8,17 @@
rotate_right,
is_cyclic,
merge_two_list, merge_two_list_recur,
is_palindrome, is_palindrome_stack, is_palindrome_dict
is_palindrome, is_palindrome_stack, is_palindrome_dict,
RandomListNode, copy_random_pointer_v1, copy_random_pointer_v2
)

import unittest

class Node(object):
def __init__(self, x):
self.val = x
self.next = None


# Convert from linked list Node to list for testing
def convert(head):
ret = []
Expand All @@ -26,6 +29,7 @@ def convert(head):
current = current.next
return ret


class TestSuite(unittest.TestCase):
def setUp(self):
# list test for palindrome
Expand Down Expand Up @@ -69,7 +73,6 @@ def test_is_sorted(self):
self.assertFalse(is_sorted(head))

def test_remove_range(self):

# Test case: middle case.
head = Node(0)
head.next = Node(1)
Expand Down Expand Up @@ -163,12 +166,50 @@ def test_merge_two_list(self):
def test_is_palindrome(self):
self.assertTrue(is_palindrome(self.l))
self.assertFalse(is_palindrome(self.l1))

def test_is_palindrome_stack(self):
self.assertTrue(is_palindrome_stack(self.l))
self.assertFalse(is_palindrome_stack(self.l1))

def test_is_palindrome_dict(self):
self.assertTrue(is_palindrome_dict(self.l))
self.assertFalse(is_palindrome_dict(self.l1))

def test_solution_0(self):
self._init_random_list_nodes()
result = copy_random_pointer_v1(self.random_list_node1)
self._assert_is_a_copy(result)

def test_solution_1(self):
self._init_random_list_nodes()
result = copy_random_pointer_v2(self.random_list_node1)
self._assert_is_a_copy(result)

def _assert_is_a_copy(self, result):
self.assertEqual(5, result.next.next.next.next.label)
self.assertEqual(4, result.next.next.next.label)
self.assertEqual(3, result.next.next.label)
self.assertEqual(2, result.next.label)
self.assertEqual(1, result.label)
self.assertEqual(3, result.next.next.next.next.random.label)
self.assertIsNone(result.next.next.next.random)
self.assertEqual(2, result.next.next.random.label)
self.assertEqual(5, result.next.random.label)
self.assertEqual(4, result.random.label)

def _init_random_list_nodes(self):
self.random_list_node1 = RandomListNode(1)
random_list_node2 = RandomListNode(2)
random_list_node3 = RandomListNode(3)
random_list_node4 = RandomListNode(4)
random_list_node5 = RandomListNode(5)

self.random_list_node1.next, self.random_list_node1.random = random_list_node2, random_list_node4
random_list_node2.next, random_list_node2.random = random_list_node3, random_list_node5
random_list_node3.next, random_list_node3.random = random_list_node4, random_list_node2
random_list_node4.next = random_list_node5
random_list_node5.random = random_list_node3


if __name__ == "__main__":
unittest.main()

0 comments on commit 8694de5

Please sign in to comment.