{"id":20409704,"url":"https://github.com/sleekpanther/counting-inversions","last_synced_at":"2025-03-05T02:43:14.369Z","repository":{"id":115108613,"uuid":"93785790","full_name":"SleekPanther/counting-inversions","owner":"SleekPanther","description":"Finds how similar 2 lists of rating are using the Divide and Conquer approach. Extension of MergeSort that actually displays the specific inversions as well as just counting the total number.","archived":false,"fork":false,"pushed_at":"2017-06-11T01:02:56.000Z","size":431,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-15T13:08:07.135Z","etag":null,"topics":["algorithm","algorithm-design","arrays","count","counting-inversions","dissimilarity","divide-and-conquer","invert","merge","mergesort","mergesort-algorithm","noah","noah-patullo","pattullo","pattulo","patullo","patulo","ratings","similarity","sorting"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SleekPanther.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-06-08T19:44:29.000Z","updated_at":"2017-06-09T18:56:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"e3b22e32-a7d3-4243-b8ac-c47db5624609","html_url":"https://github.com/SleekPanther/counting-inversions","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SleekPanther%2Fcounting-inversions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SleekPanther%2Fcounting-inversions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SleekPanther%2Fcounting-inversions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SleekPanther%2Fcounting-inversions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SleekPanther","download_url":"https://codeload.github.com/SleekPanther/counting-inversions/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241955039,"owners_count":20048405,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithm","algorithm-design","arrays","count","counting-inversions","dissimilarity","divide-and-conquer","invert","merge","mergesort","mergesort-algorithm","noah","noah-patullo","pattullo","pattulo","patullo","patulo","ratings","similarity","sorting"],"created_at":"2024-11-15T05:43:01.375Z","updated_at":"2025-03-05T02:43:14.361Z","avatar_url":"https://github.com/SleekPanther.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Counting Inversions\nFinds how similar 2 lists of rating are using the Divide and Conquer approach. Extension of MergeSort that actually displays the specific inversions as well as just counting the total number.\n\n## Problem Statement\nCompare ratings of n items between 2 lists. How similar are they (how many inversions)?  \n1 list is ranked; 1, 2, 3, ... , n  \nThe other list has arbitrary order: a\u003csub\u003e1\u003c/sub\u003e, a\u003csub\u003e2\u003c/sub\u003e, a\u003csub\u003e3\u003c/sub\u003e, ... , a\u003csub\u003en\u003c/sub\u003e (values in the array at an index)  \n\u003cimg src=\"images/you-me-lists.png\" width=\"300\"\u003e  \n**Inversion:** index `i` is less then index `j`, but the value at `i` is greater than the value at `j` (`i` \u003c `j`, but a\u003csub\u003ei\u003c/sub\u003e \u003e a\u003csub\u003ej\u003c/sub\u003e)  \n**This example has 6 inversions: (4,1), (4,2), (4,3), (3,1), (3,2), (2,1)**\n\n**Use the *array index* as the reference ranking and the *array entry* as the compared ranking**  \nTo find the number of inversions, we can just write out the 2nd list below the 1st lists which is in sorted order \u0026 **draw lines connecting identical values**  \n\u003cimg src=\"images/array1-crossed.png\" width=\"400\"\u003e  \nNow count the number of **times these lines cross** (actual inversions are in colored parentheses)  \n\u003cimg src=\"images/array1-inversions.png\" width=\"500\"\u003e  \nAgain, this example has 6 inversions: (4,1), (4,2), (4,3), (3,1), (3,2), (2,1)\n\n**If a list has no inversions, it is already sorted and no crossed lines**  \n\u003cimg src=\"images/no-inversions-crossed.png\" width=\"300\"\u003e  \n\nThis reduces down to just comparing the 2nd list to its sorted order\n\n## Solution\nOnly requires a slight modification to MergeSort  \n![](images/pseudocode.png)  \n**When merging the 2 sublists, if a value is copied from the right half, then it is greater than all the remaining elements in the left half so the inversion could should increase by the number of elements remaining in the left half**  \n**This is a *Split Inversion***  \nMergeSort stages:  \n![](images/array1-mergesort-divide.png)  \n*In the actual algorithm, the left half happens 1st, but I write both divide steps here for simplicity*  \n- In **Merge 1**, the item from the right half (`3`) is copied 1st so we have an inversion (4,3)\n- In **Merge 2**, item from the right half (`1`) is copied 1st so we have the inversion (2,1)\n- In **Merge 3**, `1` is \u003c both items in the left half so 2 inversions: (3,1) \u0026 4,1)\n- Also in **Merge 3**, `2` is \u003c both items in the left half so 2 more inversions: (3,2) \u0026 4,2)\n\nDivide step is the same, but now count the number of inversions in the left half, right half \u0026 split inversions  \nThe Divide stage counts the inversion in the left \u0026 right halves, split inversions are counted in the Merge stage\n\n## Runtime\nT(n) ≤ T(⌊n/2⌋)+ T(| n/2 |)+ O(n)  \n⇒ **T(n) = O(n log n)**  \n(by solving the same recurrence relation as MergeSort)\n\n## Code Details\n- Return types of the classic mergeSort have been changed to `int` since they now return the number of inversions as well as sorting\n- This Algorithm is instance-based instead of a `static` sort method\n- The magic happens in the `else` of the `mergeAndCount()` **Main Loop** (this main loop copies the smallest item for a sub-array until 1 sub-array runs out)\n  - The `else` is only entered if the item in the left half is NOT smaller than the item in the right half\n  - `inversionCount += center-leftPos;` increments `inversionCount` by the number of items remaining in the left half\n  - Then a for loop goes from the current `leftPos` until the end of the left half \u0026 adds the inversions to a bookkeeping 2D `ArrayList`\n    - `inversions.add(new ArrayList\u003cInteger\u003e(Arrays.asList(array[i], array[rightPos-1])));`\n      - `array[rightPos-1]` is the item from the right sub-array because a few lines above is: `array[ rightPos++ ];` which increments `rightPos`, so the actual value is 1 less (it's previous value)\n\n## References\n- [Counting Inversions - Kevin Wayne](https://www.cs.princeton.edu/~wayne/kleinberg-tardos/pdf/05DivideAndConquerI.pdf#page=12)\n- [MergeSort Code - Data Structures and Algorithm Analysis in Java (Third Edition) by Mark Allen Weiss](http://users.cis.fiu.edu/~weiss/dsaajava3/code/Sort.java)\n- [Part 1: O(n log n) Algorithm for Counting Inversions - Free Engineering Lectures](https://www.youtube.com/watch?v=4IvYaOY8Pxw)\n- [Part 2: O(n log n) Algorithm for Counting Inversions - Free Engineering Lectures](https://www.youtube.com/watch?v=PLkuid82dbc)\n- [Count Inversions - GeeksForGeeks](http://www.geeksforgeeks.org/counting-inversions/)  \nChanged specific implementation of `inversionCount`\n- [Counting inversions - toto2 (Stack Overflow)](https://codereview.stackexchange.com/q/54756)  \nHelped figure out Left Boundary \u0026 test cases\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsleekpanther%2Fcounting-inversions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsleekpanther%2Fcounting-inversions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsleekpanther%2Fcounting-inversions/lists"}