Posted in Better Programming

Essential Git Commands To Improve Project Workflow

1. Convert a repository into a Git repository

This will create a .git sub folder in your project directory.

$ cd <PROJECT_DIRECTORY>
$ git init

2. Clone a repo and pull the latest changes

$ git clone <GIT URL>
$ git pull

3. Create a new branch

$ git checkout -b <DESCRIPTIVE BRANCH NAME>

# View all branches
$ git branch

# Checkout an existing branch
$ git checkout <BRANCH_NAME>

4. Delete a branch

# Delete a local branch
$ git branch -d <BRANCH NAME>

# Delete a remote branch
$ git push origin --delete <BRANCH NAME TO DELETE>

5. Rename a branch

# From the branch to be renamed
$ git branch -m <NEW BRANCH NAME>

# From another branch
$ git branch -m <OLD BRANCH NAME> <NEW BRANCH NAME>

# Steps to rename a remote branch after following the above steps
$ git push origin -u <NEW BRANCH NAME>

# Delete old remote branch
$ git push origin --delete <OLD BRANCH NAME>

6. Pull the latest changes from the master branch

There are two ways to pull the latest changes from master into your branch. Tip: If you are working on a complex change, pull the changes from master often (once or twice everyday depending on how frequently new changes are shipped to master). This will save a lot of time not having to deal with merge conflicts.

Do a merge

Note: In this way, you can checkout master and pull all the latest changes into your branch but will have to solve multiple conflicts that arise from this scenario. Solve any conflicts that come up after executing the following commands.

$ git checkout <YOUR BRANCH>
$ git merge master

Do a rebase

$ git checkout <YOUR BRANCH>
$ git rebase master

Not sure whether to do a merge or rebase? Checkout this tutorial on merging vs rebasing.

7. Commit and push changes

# Check the changes you have made
$ git diff

# Stage all the changes
$ git add .

# Stage only a single file
$ git add <FILE NAME>

# Commit the changes
$ git commit -m "Commit message"

# Stage changes and commit one-liner
$ git commit -am "Commit message"

# Check if everything looks okay
$ git status 

# Push changes to remote
$ git push origin master

8. Save changes locally without committing

# Save uncommitted changes in a stack where you can get it back later
$ git stash 

# To retrieve the stash and apply it on top of your branch
$ git stash apply 

# Save stash with a name
$ git stash push -m "Name of the stash"

# To view list of all stashes
$ git stash list 

# Apply a stash with index n
$ git stash apply stash@{n}

# Apply a stash and pop it from stack
$ git stash pop stash@{n}

9. Pull the latest changes into a branch

This can result in change conflicts which have to be resolved.

$ git pull

10. Check commit history

This will display an entire scrollable commit history of your repository.

$ git log

11. Merge branch with master

# Squash and merge if there are too many noisy commits
$ git checkout master
$ git merge --squash <BRANCH TO MERGE>
$ git commit

# Regular merge
$ git checkout master
$ git merge <BRANCH TO MERGE>
$ git push origin master

12. Something’s on fire! Revert!

# Revert a single commit
$ git revert <COMMIT SHA>

# Revert Multiple commits
# Note: Works well only if there are no merge commits done
$ git revert <OLDEST COMMIT SHA>..<LATEST COMMIT SHA>

# Revert multiple commits and retain commit history
# Note: Works with merge commits
$ git checkout -f <TARGET COMMIT SHA> -- .
$ git commit -m 'revert to <TARGET COMMIT SHA>'
$ git diff HEAD # To check

These commands have helped me get 90% of my work done during all these years. Special scenarios have been pretty rare and they definitely warrant a deeper understanding before diving into them. Good luck!

Posted in Arrays and Strings, Data Structures/ Leetcode, Two Pointer Technique

[Problem Solving] Three Sum – Using Two Sum

To understand the following problem, we will be using what we learnt in the two sum problem. If you haven’t read it yet, do make sure to understand it before proceeding. Here’s the link.

Problem Statement

We have an array of integers called nums. We need to return three numbers let’s call it nums[i] = x, nums[j] = y and nums[k] = z that add up to 0. The indices of the returned numbers should all be unique ie., i != j != k

Assumptions

  • Solution set should not contain duplicate triplets
  • Empty array results in an empty set
  • If there are less than three numbers in the input array, return an empty set

Examples

Input: nums = [-1,0,1,2,-1,-4]

Output: [[-1,-1,2],[-1,0,1]]

Thought process

The brute force way to do this would be to loop using three for loops to search for three numbers in the array that sum up to 0. But this would have an O(n3) time complexity. So we need to be slightly better than that. The next best in time is an O(n2) solution. Remember that we should not return duplicate indices.

Let’s say nums[i] + nums[j] + nums[k] = 0

Then nums[i] + nums[j] = – nums[k]

This now resembles a two sum problem where we need to look for nums[i] and nums[j] such that they add up to a target = – nums[k]

To condense the problem, what we can do is loop through the array from k = 0 to k = n-1 and for every nums[k], find two numbers nums[i] and nums[j] that add up to a target = – nums[k].

How can we avoid adding duplicate triplets to the results list? A naive solution is to add all the duplicates to the result list and in the end return the set(result) to remove duplicates. This way we still do unnecessary work on finding the same two numbers that add up to a target value -nums[k].

To avoid executing a two sum loop on duplicates, let’s reuse our solution from the two sum problem where the input array was sorted and contained duplicates. We can sort the nums list and skip searching for two sum values whenever the current nums[k] = nums[k-1]. Sorting makes it easier to club duplicate values together. For ex:

Input: [-1,0,1,2,-1,-4]

Sorted List: [-4, -1, -1, 0 ,1,2]

One of the solutions here that adds up to 0 will be [-1, 0,1]. Now if we did not skip for target = nums[2] = -1, we will again get a solution set of [-1, 0, 1] in the result.

Complexity

O(N2) time complexity and O(1) extra space

Solution

def three_sum(nums):
    """
    :type nums: List[int]
    :rtype: List[List[int]]
    """
    # Edge case when the array is empty
    if not nums:
       return []
    
    n = len(nums)
    # Another edge case when the input array does not have 3 elements
    if len(nums) < 3:
       return []
        
    results = []

    # Sorting helps to club duplicate values together
    nums.sort()
        
    for k in range(0, n):
        # If the current num is equal to the previous value, then skip execution because we will be getting a duplicate solution set
        if k > 0 and nums[k] == nums[k-1]:
            continue
                
            target = -1 * nums[k]
            start = k + 1
            end = n - 1
            
            two_sum(nums, target, results, start, end)
    return results

# Same as the two sum solution that we coded in the previous article
def two_sum(nums, target, results, s, e): 

    while s < e:
            
        if nums[s] + nums[e] == target:
            results.append([nums[s], nums[e], -target])
            s += 1 # Advance the starting pointer to continue to look for other solutions

            # Skip duplicate solutions in two sum
            while s < e and nums[s] == nums[s-1]:
                s += 1
            
        elif nums[s] + nums[e] < target:
           s += 1
        else:
           e -= 1