It can be solved in a naive manner to search for the start and end in a linear runtime O(n). But a better solution is to use Binary Search which runs in O(logn) time.

A typical binary search method looks like this if the array has unique and sorted numbers.

```
private int binarySearch(int[] nums, int target, int l, int r) {
int result = -1;
while (l<=r){
int mid = (l+r)/2;
if(nums[mid]==target){
return mid;
} else if (nums[mid] < target) {
l = mid + 1;
} else {
r = mid - 1;
}
}
return result;
}
```

But for this problem, the Binary Search requires a little modification because of the duplicates and also that we can design it in a way to look for not only the target value but also specifically search for the starting and ending occurrence. So check out the solution below.

```
public class SearchForARange {
public int[] searchRange(int[] nums, int target) {
int[] res = new int[]{-1,-1};
if (nums.length==0) return res;
res[0] = binarySearchLeft(nums, target, 0, nums.length-1);
if (res[0]>=0) {
res[1] = binarySearchRight(nums, target, res[0], nums.length-1);
}
return res;
}
private int binarySearchLeft(int[] nums, int target, int l, int r) {
int result = -1;
while(l<=r){
int mid = (l+r)/2;
if (nums[mid] == target){
result = mid;
r = mid-1;
} else if (nums[mid] > target){
r = mid - 1;
} else {
l = mid + 1;
}
}
return result;
}
private int binarySearchRight(int[] nums, int target, int l, int r) {
int result = -1;
while (l<=r){
int mid = (l+r)/2;
if(nums[mid]==target){
result = mid;
l = mid + 1;
} else if (nums[mid] > target) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return result;
}
}
```

For understanding the logic, check out this post.

]]>A better approach is to use three-way partitioning of the array.

Below the threeWayPartitionSort() method splits the given an array, `[3,2,0,2,1,1,0,-1]`

, into three parts, where values equal to or 0 come first, in the last part, values equal to or greater than 2 show up. Anything in between stays in between. So the final result is `[-1,0,0, 1,1, 2,2,3]`

```
public class threeWayPartitionSort{
public void threeWayPartitionSort(int[] nums, int a, int b) {
int l = 0;
int r = nums.length - 1;
int i = 0;
while(i<=r){
if (nums[i]<=a) {
swap(nums, i++, l++);
} else if (nums[i]>=b){
swap(nums, i, r--);
} else {
i++;
}
}
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
public static void main(String[] args) {
nums = new int[]{3,2,0,2,1,1,0,-1};
sortColors.sortColors(nums, 0, 2);
System.out.println(Arrays.toString(nums));
}
}
```

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

Notice, that there are three pointers, `i`

for looping through the the array until it hits the right side marker `r`

, and the left side marker `l`

. Until `i`

hits `r`

, we keep looping, and each time a value below a is met it is swapped with left marker and both `l`

and `i`

are incremented. If a value greater than or equal to b is found, value at`r`

and `i`

are swapped, but only `r`

is decremented, showing that the ride side is already partitioned. For value in between, just increment `i`

. This expects, that if we move the larger values to the right region and smaller values in the left region, then every value in between should fall in the right middle region.

Using the above approach the solution for the Sort Color problem is below. This approach takes O(n) times.

```
class Solution {
public void sortColors(int[] nums) {
int l = 0;
int r = nums.length - 1;
int i = 0;
while(i<=r){
if (nums[i]==0) {
swap(nums, i++, l++);
} else if (nums[i]==2){
swap(nums, i, r--);
} else {
i++;
}
}
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
```

]]>Traditional stock prediction can be seen as a time series regression problem where many many algorithms already exist. A naive approach could be classification/regression but time series is more robust approach.

However, for a regression stock prediction model, one needs to map the predicted stock price to BUY / SELL / HOLD action space. So classification probably makes more sense. But Reinforcement Learning really helps a lot because it can optimize the total gains.

**Generic RNN, LSTM:**many resources available online**Transformer+Attention:**This Medium article and its corresponding GitHub repo applies Transformer and time embeddings which seems quite interesting**Dual-stage Attention -RNN (DA-RNN):**The paper is here https://arxiv.org/pdf/1704.02971.pdf and the implemented model is available here in this GitHub. A similar implementation in PyTorch is available here by KurochkinAlexey**Deep Reinforcement Learning:**Finally, this FinRL is an excellent library for applying Deep RL on stock prediction with demo and code examples to help you get started.

This is a work-in-progress note. So will update this as needed.

]]>```
public class FindPeakElement {
int[] nums;
public int findPeakElement(int[] nums){
this.nums = nums;
return search(0, this.nums.length-1);
}
private int search(int l, int r) {
if(l==r) return l;
int mid = (l+r)/2;
if (nums[mid]>nums[mid+1]){
return search(l, mid);
} else return search(mid+1, r);
}
}
```

```
public class FindPeakElement {
int[] nums;
public int findPeakElement(int[] nums){
this.nums = nums;
return searchIterative(0, this.nums.length-1);
}
private int searchIterative(int l, int r){
while(l<r){
int mid = (l+r)/2;
if (nums[mid]>nums[mid+1]){
r = mid;
} else {
l = mid+1;
}
}
return l;
}
```

]]>QuickSelect is a sorting algorithm that uses partitioning scheme like Hoare’s or Lomuto’s. It finds the k-th smallest value in O(n) time. It uses divide and conquer technique. It divides the space using partition function and then recursively sorts the left or right part until it finds the partition.

```
private void quickSelect(int left, int right){
if (left < right) {
int p = partition(left, right);
if (kSmallest <= p) quickSelect(left, p);
else {
quickSelect(p+1, right);
}
}
}
```

Notice if (kSmallest <= p), then we know the `nums`

array is partitioned from `left to p`

which has values smaller than the values on the right portion from indices `p+1 to right`

. So we only recursively sort the left.

If that is not the case, then we can sort on the right. But we cannot stop if p==kSmallest like in Lomuto’s partition because Hoare’s does not ensure that the value at the partition is the final position of the number.

Hoare’s partitioning is shown below. This partitioning scheme is much faster than Lomuto’s. There are plenty of online resources on this most of them are confusing in the one on Wikipedia. I wrote piece here on QuickSort that could help.

```
private int partition(int left, int right){
int p = (left+right)/2;
int pVal = nums[p];
int i = left - 1;
int j = right + 1;
while(true){
do {
i++;
} while( nums[i] < pVal);
do {
j--;
} while (nums[j] > pVal);
if(i<j){
swap(i,j);
} else{
return j;
}
}
}
```

The solution below beats 100% Java submissions on LeetCode for runtime.

```
public class KthLargestElement {
int kSmallest;
int[] nums;
public int findKthLargest(int[] nums, int k) {
this.nums = nums;
this.kSmallest = nums.length-k;
quickSelect(0, nums.length-1);
return nums[kSmallest];
}
private void quickSelect(int left, int right){
if (left < right) {
int p = partition(left, right);
if (kSmallest <= p) quickSelect(left, p);
else {
quickSelect(p+1, right);
}
}
}
private int partition(int left, int right){
int p = (left+right)/2;
int pVal = nums[p];
int i = left - 1;
int j = right + 1;
while(true){
do {
i++;
} while( nums[i] < pVal);
do {
j--;
} while (nums[j] > pVal);
if(i<j){
swap(i,j);
} else{
return j;
}
}
}
private void swap(int i, int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
```

]]>- This website by J Al-Ammar is excellent
- The next best resource is this annotated implementation of Transformer in PyTorch from Harvard University
- Second, read this article called “Attention! Attention!” by Lilian Weng
- For further background on Word Embeddings, look into this post by Jason Brownlee.

**Optional: **Learn about `FOREIGN KEY`

and `PRIMARY KEY`

and the different Database Normalization types from this Wikipedia page. Probably you will need only up to 1st to 4th Normal Form of a database.

These basic concepts are useful to understand why we need table joins. But not entirely essential.

Also this note does not talk about creating database schema and modifying it.

In the example below, you are querying two columns, `column_name_1, column_name_2`

from the `table`

but we only want the unique values from the second column, so we use `DISTINCT`

. The conditions to select particular data are added in the `WHERE`

clause. The two selected columns are then sorted first by ascending order and then by descending order using the `ORDER BY`

clause. And finally we are only interested in maximum 10 rows.

```
SELECT column_name_1, DISTINCT(column_name_2)
FROM table_name
WHERE column_name_1 = "abc" and column_name_2 = "xyz"
ORDER BY column_name_1 ASC, column_name_2 DESC
LIMIT 10
```

Another simple clause is CASE WHEN which is useful as a if-else block. Between a `CASE ... END`

There can be as many `WHEN`

block and then one `ELSE`

clause

```
CASE
WHEN condition_1 THEN result_1
WHEN condition_2 THEN result_2
ELSE final_value
END
```

Union enables stacking two table with same columns one on top of the other. `UNION`

only keeps distinct rows from two tables, on the other hand `UNION ALL`

keeps all rows.

`HAVING`

clauseAggregate functions are basically statistical summary functions like SUM(), MIN(), MAX(), AVG() etc. See the section titled “Rank, Window, Lag, Lead” below.

`OVER()`

, `PARTITION BY`

From SQLShack.com “In the SQL GROUP BY clause, we can use a column in the select statement if it is used in Group by clause as well. It does not allow any column in the select clause that is not part of GROUP BY clause”. Definitely check out the link to get a clear idea about these useful clauses and their differences.

Joins are very intuitive but may become quite complex especially when used with nested sub-queries.

There are various types of SQL joins. Cross join simply makes all the combinations of the two tables as shown in the image from SQLShack.com. You should check out their post on Cross join, it is very detailed!

Cross Join can be run by this example where `table_name_1`

and `table_name_2`

are cross joined. This is often time very inefficient. So be careful with cross joins and look out for ways to avoid it.

```
SELECT column_name_1, column_name_2
FROM table_name_1,table_name_2
```

I find this image below to explain the SQL joins very effective

Carsson Forter writes, “**By filtering and aggregating your data before joining, you write the most efficient SQL. **Joins are expensive to process so you want the fewest possible rows before joining two tables together… if you have a `JOIN`

and a `WHERE`

clause in the same CTE, SQL processes the `JOIN`

first”.

So trying to filter and then joining is typically more efficient. That brings us to more advanced topics, including subqueries and CTEs.

CTEs gives a way to store some queried data with a name so that it can be used in more complex queries. That way, CTEs help write complex SQL queries in a cleaner way.

CTEs commonly have this syntax, you can have multiple CTE’s. Source here

```
WITH
cte1 as (SELECT * from table WHERE ...),
cte2 as (SELECT * from table WHERE ...)
select * from cte1 union select * from cte2
```

This article by Carsson Forter provides a great example of using multiple CTEs to calculate the avg time between two transactions of a customer. This is his example which also used `group by`

clause to aggregate data by user name.

```
-- First, find all of user_a's transactions today
with user_a_trans as (
SELECT username, time
FROM transactions
WHERE day = '2017-09-08'
AND username = 'user_a'),
-- Join each transaction to all transactions occurring after it
joined_trans as (
SELECT username, time, future_times
FROM user_a_trans a
INNER JOIN user_a_trans b
ON b.time > a.time),
-- Find the immediate next transaction using MIN()
next_trans as (
SELECT username, time, MIN(future_times) as next_time
FROM joined_trans
GROUP BY username, time)
-- Average difference of the time and the next transaction's time
SELECT AVG(next_time - time) as avg_time_to_next_transaction
from next_trans;
```

The Window clause is useful to set a condition over which data is split. `WINDOW`

can be at a single location and referred to while calling aggregation functions like `SUM()`

and `AVG()`

. This is the link for the code below.

```
SELECT sum(salary) OVER w, avg(salary) OVER w
FROM empsalary
WINDOW w AS (PARTITION BY depname ORDER BY salary DESC);
```

For `LAG`

, see a thorough explanations here. The same logic applies on `LEAD`

For rank functions, `ROW_NUMBER()`

, `RANK(),`

and `DENSE_RANK()`

, see this resource.

A good example of these functions is found on this website. Copying the example query here

```
USE AdventureWorks2012;
GO
SELECT JobTitle, LastName, VacationHours,
FIRST_VALUE(LastName) OVER (
PARTITION BY JobTitle
ORDER BY VacationHours ASC
ROWS UNBOUNDED PRECEDING )
AS FewestVacationHours
FROM HumanResources.Employee AS e
INNER JOIN Person.Person AS p
ON e.BusinessEntityID = p.BusinessEntityID
ORDER BY JobTitle;
```

This is another important group of SQL queries practically useful but not talked about in most cases.

]]>**Semantic Segmentation:** Class distribution per pixel

**Instance Segmentation: ** Class distribution per pixel with unique ID

**Object Detection:** List of bounding boxes with Class distribution per box

So essentially they are almost the same thing except the gradients of the kernels will still remain flipped!

But that little difference does not matter! Because no matter which way the kernel is flipped, it can still learn the best kernel values for the operation. So turns out we can enjoy the little mathematical convenience without any issue!

But there is more to that! It turns out, the derivative of the cross-correlation is the convolution!!! So it is going to be very useful in the backward pass of the CNN because we know how to convolve!! If we instead used convolution in the forward pass, the backward will be cross-correlation!

Math is amazing! ]]>